diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index fcf4bf4a7b7a4..f783371eb1cd9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -721,8 +721,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { )); let can_subst = |ty: Ty<'tcx>| { // Normalize before comparing to see through type aliases and projections. - let old_ty = ty::EarlyBinder::bind(ty).instantiate(tcx, generic_args); - let new_ty = ty::EarlyBinder::bind(ty).instantiate(tcx, new_args); + let old_ty = ty::EarlyBinder::bind(tcx, ty).instantiate(tcx, generic_args); + let new_ty = ty::EarlyBinder::bind(tcx, ty).instantiate(tcx, new_args); if let Ok(old_ty) = tcx.try_normalize_erasing_regions( self.infcx.typing_env(self.infcx.param_env), old_ty, diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs index 1348f30b4c980..39d63a4db5104 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs @@ -512,7 +512,7 @@ impl<'tcx> FallibleTypeFolder> for ToArgRegionsFolder<'_, 'tcx> { } }, ))?; - ty::AliasTy::new_from_args(tcx, kind, args).to_ty(tcx) + ty::AliasTy::new_from_args(tcx, kind, args, ty::IsRigid::No).to_ty(tcx) } _ => ty.try_super_fold_with(self)?, diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index b22afca847aa9..26ecbb621c270 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -349,7 +349,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { self.instance.instantiate_mir_and_normalize_erasing_regions( self.tcx, ty::TypingEnv::fully_monomorphized(), - ty::EarlyBinder::bind(value), + ty::EarlyBinder::bind(tcx, value), ) } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index d2591139d6edc..dd26ce098e092 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -117,7 +117,7 @@ fn make_mir_scope<'ll, 'tcx>( let callee = cx.tcx.instantiate_and_normalize_erasing_regions( instance.args, cx.typing_env(), - ty::EarlyBinder::bind(callee), + ty::EarlyBinder::bind(cx.tcx, callee), ); debug_context.inlined_function_scopes.entry(callee).or_insert_with(|| { let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty()); diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 84013a00d79df..9b489ca1481ea 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -134,7 +134,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.instance.instantiate_mir_and_normalize_erasing_regions( self.cx.tcx(), self.cx.typing_env(), - ty::EarlyBinder::bind(value), + ty::EarlyBinder::bind(self.cx.tcx(), value), ) } } @@ -194,7 +194,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let monomorphized_mir = instance.instantiate_mir_and_normalize_erasing_regions( tcx, ty::TypingEnv::fully_monomorphized(), - ty::EarlyBinder::bind(mir.clone()), + ty::EarlyBinder::bind(tcx, mir.clone()), ); mir = tcx.arena.alloc(optimize_use_clone::(cx, monomorphized_mir)); } diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index bdefacefd20b9..02f8756f16631 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -67,7 +67,7 @@ fn inline_to_global_operand<'a, 'tcx, Cx: LayoutOf<'tcx, LayoutOfResult = TyAndL .instantiate_mir_and_normalize_erasing_regions( cx.tcx(), cx.typing_env(), - ty::EarlyBinder::bind(value.const_), + ty::EarlyBinder::bind(cx.tcx(), value.const_), ) .eval(cx.tcx(), cx.typing_env(), value.span) .expect("erroneous constant missed by mono item collection"); @@ -75,7 +75,7 @@ fn inline_to_global_operand<'a, 'tcx, Cx: LayoutOf<'tcx, LayoutOfResult = TyAndL let mono_type = instance.instantiate_mir_and_normalize_erasing_regions( cx.tcx(), cx.typing_env(), - ty::EarlyBinder::bind(value.ty()), + ty::EarlyBinder::bind(cx.tcx(), value.ty()), ); let string = common::asm_const_to_str( @@ -91,7 +91,7 @@ fn inline_to_global_operand<'a, 'tcx, Cx: LayoutOf<'tcx, LayoutOfResult = TyAndL let mono_type = instance.instantiate_mir_and_normalize_erasing_regions( cx.tcx(), cx.typing_env(), - ty::EarlyBinder::bind(value.ty()), + ty::EarlyBinder::bind(cx.tcx(), value.ty()), ); let instance = match mono_type.kind() { diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index 62ec0d2ef8bf4..d3f6447249867 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -70,8 +70,8 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>( body: &'tcx mir::Body<'tcx>, ) -> InterpResult<'tcx, R> { let tcx = *ecx.tcx; - let layout = - ecx.layout_of(body.bound_return_ty().instantiate(tcx, cid.instance.args).skip_norm_wip())?; + let layout = ecx + .layout_of(body.bound_return_ty(tcx).instantiate(tcx, cid.instance.args).skip_norm_wip())?; let (intern_kind, ret) = setup_for_eval(ecx, cid, layout)?; trace!( diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 7dc6d292a94af..affac3e4c7c67 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -355,7 +355,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { .try_instantiate_mir_and_normalize_erasing_regions( *self.tcx, self.typing_env, - ty::EarlyBinder::bind(value), + ty::EarlyBinder::bind(self.tcx.tcx, value), ) .map_err(|_| ErrorHandled::TooGeneric(self.cur_span())) } diff --git a/compiler/rustc_hir_analysis/src/check/always_applicable.rs b/compiler/rustc_hir_analysis/src/check/always_applicable.rs index 02870afeb4ef1..f018e073f0906 100644 --- a/compiler/rustc_hir_analysis/src/check/always_applicable.rs +++ b/compiler/rustc_hir_analysis/src/check/always_applicable.rs @@ -192,8 +192,9 @@ fn ensure_all_fields_are_const_destruct<'tcx>( let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let impl_span = tcx.def_span(impl_def_id.to_def_id()); - let env = - ty::EarlyBinder::bind(tcx.param_env(impl_def_id)).instantiate_identity().skip_norm_wip(); + let env = ty::EarlyBinder::bind(tcx, tcx.param_env(impl_def_id)) + .instantiate_identity() + .skip_norm_wip(); let args = ty::GenericArgs::identity_for_item(tcx, impl_def_id); let destruct_trait = tcx.lang_items().destruct_trait().unwrap(); for field in tcx.adt_def(adt_def_id).all_fields() { @@ -281,7 +282,7 @@ fn ensure_impl_predicates_are_implied_by_item_defn<'tcx>( // reference the params from the ADT instead of from the impl which is bad UX. To resolve // this we "rename" the ADT's params to be the impl's params which should not affect behaviour. let impl_adt_ty = Ty::new_adt(tcx, tcx.adt_def(adt_def_id), adt_to_impl_args); - let adt_env = ty::EarlyBinder::bind(tcx.param_env(adt_def_id)) + let adt_env = ty::EarlyBinder::bind(tcx, tcx.param_env(adt_def_id)) .instantiate(tcx, adt_to_impl_args) .skip_norm_wip(); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index f90311c66d600..95ceeed5d5c15 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -2314,6 +2314,8 @@ pub(super) fn check_potentially_region_dependent_goals<'tcx>( let predicate = fold_regions(tcx, *predicate, |_, _| { infcx.next_region_var(RegionVariableOrigin::Misc(cause.span)) }); + // FIXME: perhaps not here. + let predicate = ty::reset_rigid_aliases(tcx, predicate); ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate)); } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 234231ed37fed..9307122b042ac 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -761,7 +761,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( Ok(ty) => ty, Err(guar) => Ty::new_error(tcx, guar), }; - remapped_types.insert(def_id, ty::EarlyBinder::bind(ty)); + remapped_types.insert(def_id, ty::EarlyBinder::bind(tcx, ty)); } Err(err) => { // This code path is not reached in any tests, but may be @@ -783,11 +783,14 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( if !remapped_types.contains_key(assoc_item) { remapped_types.insert( *assoc_item, - ty::EarlyBinder::bind(Ty::new_error_with_message( + ty::EarlyBinder::bind( tcx, - return_span, - "missing synthetic item for RPITIT", - )), + Ty::new_error_with_message( + tcx, + return_span, + "missing synthetic item for RPITIT", + ), + ), ); } } @@ -2739,6 +2742,7 @@ fn param_env_with_gat_bounds<'tcx>( tcx, trait_ty.def_id, rebased_args, + ty::IsRigid::No, ), term: normalize_impl_ty.into(), }, diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index dd506dd2b7fc9..6e3cde2c14444 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1613,7 +1613,7 @@ pub(super) fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, def_id: } let mut param_count = CountParams::default(); let has_region = pred.visit_with(&mut param_count).is_break(); - let instantiated_pred = ty::EarlyBinder::bind(pred).instantiate(tcx, args); + let instantiated_pred = ty::EarlyBinder::bind(tcx, pred).instantiate(tcx, args); // Don't check non-defaulted params, dependent defaults (including lifetimes) // or preds with multiple params. if instantiated_pred.skip_normalization().has_non_region_param() diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 8c182f9165e13..9fe4db335ac07 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1060,7 +1060,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn bug!("unexpected sort of node in fn_sig(): {:?}", x); } }; - ty::EarlyBinder::bind(output) + ty::EarlyBinder::bind(tcx, output) } fn lower_fn_sig_recovering_infer_ret_ty<'tcx>( @@ -1380,7 +1380,7 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplTraitHeader let trait_ref = icx.lowerer().lower_impl_trait_ref(&of_trait.trait_ref, selfty); ty::ImplTraitHeader { - trait_ref: ty::EarlyBinder::bind(trait_ref), + trait_ref: ty::EarlyBinder::bind(tcx, trait_ref), safety: of_trait.safety, polarity: polarity_of_impl(tcx, of_trait, is_rustc_reservation), constness: impl_.constness, @@ -1600,7 +1600,7 @@ fn const_param_default<'tcx>( default_ct, tcx.type_of(def_id).instantiate(tcx, identity_args).skip_norm_wip(), ); - ty::EarlyBinder::bind(ct) + ty::EarlyBinder::bind(tcx, ct) } fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKind { @@ -1708,7 +1708,7 @@ fn const_of_item<'tcx>( tcx.def_span(def_id), "cannot call const_of_item on a non-type_const", ); - return ty::EarlyBinder::bind(Const::new_error(tcx, e)); + return ty::EarlyBinder::bind(tcx, Const::new_error(tcx, e)); } }; let icx = ItemCtxt::new(tcx, def_id); @@ -1720,8 +1720,8 @@ fn const_of_item<'tcx>( if let Err(e) = icx.check_tainted_by_errors() && !ct.references_error() { - ty::EarlyBinder::bind(Const::new_error(tcx, e)) + ty::EarlyBinder::bind(tcx, Const::new_error(tcx, e)) } else { - ty::EarlyBinder::bind(ct) + ty::EarlyBinder::bind(tcx, ct) } } diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 4409f2c068eb8..38f009afc94cc 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -430,7 +430,7 @@ pub(super) fn explicit_item_bounds_with_filter( let opaque_ty = tcx.hir_node_by_def_id(opaque_def_id.expect_local()).expect_opaque_ty(); let bounds = associated_type_bounds(tcx, def_id, opaque_ty.bounds, opaque_ty.span, filter); - return ty::EarlyBinder::bind(bounds); + return ty::EarlyBinder::bind_no_rigid_aliases(bounds); } Some(ty::ImplTraitInTraitData::Impl { .. }) => { span_bug!(tcx.def_span(def_id), "RPITIT in impl should not have item bounds") @@ -486,7 +486,7 @@ pub(super) fn explicit_item_bounds_with_filter( node => bug!("item_bounds called on {def_id:?} => {node:?}"), }; - ty::EarlyBinder::bind(bounds) + ty::EarlyBinder::bind_no_rigid_aliases(bounds) } pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<'_, ty::Clauses<'_>> { @@ -515,9 +515,12 @@ pub(super) fn item_non_self_bounds( let all_bounds: FxIndexSet<_> = tcx.item_bounds(def_id).skip_binder().iter().collect(); let own_bounds: FxIndexSet<_> = tcx.item_self_bounds(def_id).skip_binder().iter().collect(); if all_bounds.len() == own_bounds.len() { - ty::EarlyBinder::bind(ty::ListWithCachedTypeInfo::empty()) + ty::EarlyBinder::bind(tcx, ty::ListWithCachedTypeInfo::empty()) } else { - ty::EarlyBinder::bind(tcx.mk_clauses_from_iter(all_bounds.difference(&own_bounds).copied())) + ty::EarlyBinder::bind( + tcx, + tcx.mk_clauses_from_iter(all_bounds.difference(&own_bounds).copied()), + ) } } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index ad46f011a79cb..68e3cda71dbb4 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -748,7 +748,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>( assert_only_contains_predicates_from(filter, implied_bounds, tcx.types.self_param); - ty::EarlyBinder::bind(implied_bounds) + ty::EarlyBinder::bind_no_rigid_aliases(implied_bounds) } // Make sure when elaborating supertraits, probing for associated types, etc., @@ -922,7 +922,7 @@ pub(super) fn type_param_predicates<'tcx>( let icx = ItemCtxt::new(tcx, parent); icx.probe_ty_param_bounds(DUMMY_SP, def_id, assoc_ident) } else { - ty::EarlyBinder::bind(&[] as &[_]) + ty::EarlyBinder::bind_no_rigid_aliases(&[] as &[_]) }; let mut extend = None; @@ -970,7 +970,7 @@ pub(super) fn type_param_predicates<'tcx>( self_ty, ); - ty::EarlyBinder::bind(bounds) + ty::EarlyBinder::bind_no_rigid_aliases(bounds) } impl<'tcx> ItemCtxt<'tcx> { diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 3ac603fc715f3..f529d8f5e48b5 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -33,21 +33,27 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ return map[&trait_item_def_id]; } Err(_) => { - return ty::EarlyBinder::bind(Ty::new_error_with_message( + return ty::EarlyBinder::bind( tcx, - DUMMY_SP, - "Could not collect return position impl trait in trait tys", - )); + Ty::new_error_with_message( + tcx, + DUMMY_SP, + "Could not collect return position impl trait in trait tys", + ), + ); } } } // For an RPITIT in a trait, just return the corresponding opaque. Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => { - return ty::EarlyBinder::bind(Ty::new_opaque( + return ty::EarlyBinder::bind( tcx, - opaque_def_id, - ty::GenericArgs::identity_for_item(tcx, opaque_def_id), - )); + Ty::new_opaque( + tcx, + opaque_def_id, + ty::GenericArgs::identity_for_item(tcx, opaque_def_id), + ), + ); } None => {} } @@ -239,9 +245,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ if let Err(e) = icx.check_tainted_by_errors() && !output.references_error() { - ty::EarlyBinder::bind(Ty::new_error(tcx, e)) + ty::EarlyBinder::bind(tcx, Ty::new_error(tcx, e)) } else { - ty::EarlyBinder::bind(output) + ty::EarlyBinder::bind(tcx, output) } } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index b31da6b387299..604cd69053b8b 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -49,7 +49,7 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type( name: tcx.item_ident(parent_def_id.to_def_id()), what: "impl", }); - EarlyBinder::bind(Ty::new_error(tcx, guar)) + EarlyBinder::bind(tcx, Ty::new_error(tcx, guar)) } } @@ -94,7 +94,7 @@ pub(super) fn find_opaque_ty_constraints_for_tait( name: tcx.item_ident(parent_def_id.to_def_id()), what: "crate", }); - EarlyBinder::bind(Ty::new_error(tcx, guar)) + EarlyBinder::bind(tcx, Ty::new_error(tcx, guar)) } } @@ -247,14 +247,14 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>( let guar = tcx .dcx() .span_delayed_bug(opaque_type_span, "cannot infer type for stranded opaque type"); - return EarlyBinder::bind(Ty::new_error(tcx, guar)); + return EarlyBinder::bind(tcx, Ty::new_error(tcx, guar)); } match opaque_types_from { DefiningScopeKind::HirTypeck => { let tables = tcx.typeck(owner_def_id); if let Some(guar) = tables.tainted_by_errors { - EarlyBinder::bind(Ty::new_error(tcx, guar)) + EarlyBinder::bind(tcx, Ty::new_error(tcx, guar)) } else if let Some(hidden_ty) = tables.hidden_types.get(&def_id) { hidden_ty.ty } else { @@ -265,7 +265,7 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>( // so we can just make the hidden type be `!`. // For backwards compatibility reasons, we fall back to // `()` until we the diverging default is changed. - EarlyBinder::bind(tcx.types.unit) + EarlyBinder::bind(tcx, tcx.types.unit) } } DefiningScopeKind::MirBorrowck => match tcx.mir_borrowck(owner_def_id) { @@ -275,14 +275,14 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>( } else { let hir_ty = tcx.type_of_opaque_hir_typeck(def_id); if let Err(guar) = hir_ty.skip_binder().error_reported() { - EarlyBinder::bind(Ty::new_error(tcx, guar)) + EarlyBinder::bind(tcx, Ty::new_error(tcx, guar)) } else { assert!(!tcx.next_trait_solver_globally()); hir_ty } } } - Err(guar) => EarlyBinder::bind(Ty::new_error(tcx, guar)), + Err(guar) => EarlyBinder::bind(tcx, Ty::new_error(tcx, guar)), }, } } diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index 2d6d5a5d81f9a..173241e1b21ec 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -525,7 +525,9 @@ pub(crate) fn inherit_predicates_for_delegation_item<'tcx>( let new_pred = pred.0.fold_with(&mut self.folder); self.preds.push(( - EarlyBinder::bind(new_pred).instantiate(self.tcx, args).skip_norm_wip(), + EarlyBinder::bind(self.tcx, new_pred) + .instantiate(self.tcx, args) + .skip_norm_wip(), pred.1, )); } @@ -625,7 +627,7 @@ pub(crate) fn inherit_sig_for_delegation_item<'tcx>( let (parent_args, child_args) = get_delegation_user_specified_args(tcx, def_id); let (mut folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args); - let caller_sig = EarlyBinder::bind(caller_sig.skip_binder().fold_with(&mut folder)); + let caller_sig = EarlyBinder::bind(tcx, caller_sig.skip_binder().fold_with(&mut folder)); let sig = caller_sig.instantiate(tcx, args.as_slice()).skip_binder(); let sig_iter = sig.inputs().iter().cloned().chain(std::iter::once(sig.output())); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 6e2c7a82af3b1..f0aa0a34658b4 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -526,7 +526,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); debug!(?alias_args); - ty::AliasTerm::new_from_def_id(tcx, assoc_item.def_id, alias_args) + ty::AliasTerm::new_from_def_id(tcx, assoc_item.def_id, alias_args, ty::IsRigid::No) }) }; @@ -851,7 +851,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // `rustc_middle::ty::predicate::Clause::instantiate_supertrait` // and it's no coincidence why. let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output); - Ok(ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args).skip_norm_wip()) + Ok(ty::EarlyBinder::bind(tcx, shifted_output).instantiate(tcx, args).skip_norm_wip()) } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 5a86e8186a5aa..20cc1b326893b 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1219,7 +1219,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Type aliases defined in crates that have the // feature `lazy_type_alias` enabled get encoded as a type alias that normalization will // then actually instantiate the where bounds of. - let alias_ty = ty::AliasTy::new_from_args(tcx, ty::Free { def_id }, args); + let alias_ty = + ty::AliasTy::new_from_args(tcx, ty::Free { def_id }, args, ty::IsRigid::No); Ty::new_alias(tcx, alias_ty) } else { tcx.at(span).type_of(def_id).instantiate(tcx, args).skip_norm_wip() @@ -1368,6 +1369,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { tcx, assoc_item.def_id, alias_args, + ty::IsRigid::No, ) }); @@ -1481,6 +1483,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { tcx, ty::AliasTyKind::new_from_def_id(tcx, def_id), args, + ty::IsRigid::No, ); let ty = Ty::new_alias(tcx, alias_ty); let ty = self.check_param_uses_if_mcg(ty, span, false); @@ -1518,7 +1521,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { )? { TypeRelativePath::AssocItem(def_id, args) => { self.require_type_const_attribute(def_id, span)?; - let ct = Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(def_id, args)); + let ct = Const::new_unevaluated( + tcx, + ty::UnevaluatedConst::new(def_id, args, ty::IsRigid::No), + ); let ct = self.check_param_uses_if_mcg(ct, span, false); Ok(ct) } @@ -2017,7 +2023,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::AssocTag::Const, )?; self.require_type_const_attribute(item_def_id, span)?; - let uv = ty::UnevaluatedConst::new(item_def_id, item_args); + let uv = ty::UnevaluatedConst::new(item_def_id, item_args, ty::IsRigid::No); Ok(Const::new_unevaluated(self.tcx(), uv)) } @@ -2471,7 +2477,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { const_arg.span, "anonymous constants with lifetimes in their type are not yet supported", ); - tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, e))); + tcx.feed_anon_const_type( + anon.def_id, + ty::EarlyBinder::bind(tcx, Ty::new_error(tcx, e)), + ); return ty::Const::new_error(tcx, e); } // We must error if the instantiated type has any inference variables as we will @@ -2482,7 +2491,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { const_arg.span, "anonymous constants with inferred types are not yet supported", ); - tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, e))); + tcx.feed_anon_const_type( + anon.def_id, + ty::EarlyBinder::bind(tcx, Ty::new_error(tcx, e)), + ); return ty::Const::new_error(tcx, e); } // We error when the type contains unsubstituted generics since we do not currently @@ -2492,11 +2504,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { const_arg.span, "anonymous constants referencing generics are not yet supported", ); - tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, e))); + tcx.feed_anon_const_type( + anon.def_id, + ty::EarlyBinder::bind(tcx, Ty::new_error(tcx, e)), + ); return ty::Const::new_error(tcx, e); } - tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(ty)); + tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(tcx, ty)); } let hir_id = const_arg.hir_id; @@ -2860,7 +2875,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let _ = self .prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None); let args = self.lower_generic_args_of_path_segment(span, did, segment); - ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args)) + ty::Const::new_unevaluated( + tcx, + ty::UnevaluatedConst::new(did, args, ty::IsRigid::No), + ) } Res::Def(DefKind::Ctor(ctor_of, CtorKind::Const), did) => { assert_eq!(opt_self_ty, None); @@ -2984,10 +3002,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Some(v) => v, None => ty::Const::new_unevaluated( tcx, - ty::UnevaluatedConst { - def: anon.def_id.to_def_id(), - args: ty::GenericArgs::identity_for_item(tcx, anon.def_id.to_def_id()), - }, + ty::UnevaluatedConst::new( + anon.def_id.to_def_id(), + ty::GenericArgs::identity_for_item(tcx, anon.def_id.to_def_id()), + ty::IsRigid::No, + ), ), } } diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs index d3a57a4d8e5d3..3b60cc782ec3d 100644 --- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs +++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs @@ -59,7 +59,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { } } - ty::EarlyBinder::bind(required_predicates) + ty::EarlyBinder::bind_no_rigid_aliases(required_predicates) }) } } diff --git a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs index 23e6b2281b370..ff65e99f93d5f 100644 --- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs +++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs @@ -85,8 +85,10 @@ pub(super) fn infer_predicates( .map_or(0, |p| p.as_ref().skip_binder().len()); if item_required_predicates.len() > item_predicates_len { predicates_added.push(item_did); - global_inferred_outlives - .insert(item_did.to_def_id(), ty::EarlyBinder::bind(item_required_predicates)); + global_inferred_outlives.insert( + item_did.to_def_id(), + ty::EarlyBinder::bind_no_rigid_aliases(item_required_predicates), + ); } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 5fea7454e57ea..508d71eac30da 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -310,7 +310,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { // HACK(eddyb) should get the original `Span`. let span = tcx.def_span(def_id); - ty::EarlyBinder::bind(tcx.arena.alloc_from_iter( + ty::EarlyBinder::bind_no_rigid_aliases(tcx.arena.alloc_from_iter( self.param_env.caller_bounds().iter().filter_map(|predicate| { match predicate.kind().skip_binder() { ty::ClauseKind::Trait(data) if data.self_ty().is_param(index) => { diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index fc0c4bb0d5f5e..ffbc7ce8aa073 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -50,7 +50,9 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { &self, u: ty::UniverseIndex, ) -> Option>> { - self.placeholder_assumptions_for_next_solver.borrow().get(&u).unwrap().as_ref().cloned() + // FIXME(-Zassumptions_on_binders): We should actually make sure that + // we always register placeholder assumptions. + self.placeholder_assumptions_for_next_solver.borrow().get(&u)?.as_ref().cloned() } fn get_solver_region_constraint( diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index c0029719c6e12..331e8fe494e96 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -28,10 +28,11 @@ use rustc_middle::traits::select; use rustc_middle::traits::solve::Goal; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ - self, BoundVarReplacerDelegate, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs, - GenericArgsRef, GenericParamDefKind, InferConst, IntVid, OpaqueTypeKey, ProvisionalHiddenType, - PseudoCanonicalInput, Term, TermKind, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder, - TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingEnv, TypingMode, fold_regions, + self, AliasTermKind, BoundVarReplacerDelegate, ConstVid, FloatVid, GenericArg, GenericArgKind, + GenericArgs, GenericArgsRef, GenericParamDefKind, InferConst, IntVid, OpaqueTypeKey, + ProvisionalHiddenType, PseudoCanonicalInput, Term, TermKind, Ty, TyCtxt, TyVid, TypeFoldable, + TypeFolder, TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingEnv, TypingMode, + fold_regions, }; use rustc_span::{DUMMY_SP, Span, Symbol}; use rustc_type_ir::MayBeErased; @@ -962,6 +963,23 @@ impl<'tcx> InferCtxt<'tcx> { } } + pub fn next_term_var_for_alias( + &self, + alias: ty::AliasTerm<'tcx>, + span: Span, + ) -> ty::Term<'tcx> { + match alias.kind(self.tcx) { + AliasTermKind::ProjectionTy { .. } + | AliasTermKind::InherentTy { .. } + | AliasTermKind::OpaqueTy { .. } + | AliasTermKind::FreeTy { .. } => self.next_ty_var(span).into(), + AliasTermKind::UnevaluatedConst { .. } + | AliasTermKind::ProjectionConst { .. } + | AliasTermKind::FreeConst { .. } + | AliasTermKind::InherentConst { .. } => self.next_const_var(span).into(), + } + } + /// Return the universe that the region `r` was created in. For /// most regions (e.g., `'static`, named regions from the user, /// etc) this is the root universe U0. For inference variables or @@ -1132,6 +1150,7 @@ impl<'tcx> InferCtxt<'tcx> { self.tcx, ty::Opaque { def_id: key.def_id.into() }, key.args, + ty::IsRigid::No, )); } } diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 3d2d617cfdb29..836295b034b61 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -636,12 +636,15 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { } } - ty::Alias(data) => match self.structurally_relate_aliases { - StructurallyRelateAliases::No => { - self.generalize_alias_term(data.into()).map(|v| v.expect_type()) + ty::Alias(data) if data.is_rigid == ty::IsRigid::No => { + match self.structurally_relate_aliases { + StructurallyRelateAliases::No => { + // And should we even allow non-rigid alias here? + self.generalize_alias_term(data.into()).map(|v| v.expect_type()) + } + StructurallyRelateAliases::Yes => relate::structurally_relate_tys(self, t, t), } - StructurallyRelateAliases::Yes => relate::structurally_relate_tys(self, t, t), - }, + } _ => relate::structurally_relate_tys(self, t, t), }?; @@ -751,7 +754,9 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { // // FIXME: replace the StructurallyRelateAliases::Yes branch with // `structurally_relate_consts` once it is fully structural. - ty::ConstKind::Unevaluated(uv) => match self.structurally_relate_aliases { + ty::ConstKind::Unevaluated(uv) if uv.is_rigid == ty::IsRigid::No => match self + .structurally_relate_aliases + { // Hack: Fall back to old behavior if GCE is enabled (it used to just be the Yes // path), as doing this new No path breaks some GCE things. I expect GCE to be // ripped out soon so this shouldn't matter soon. @@ -760,14 +765,17 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { .map(|v| v.expect_const()) } _ => { - let ty::UnevaluatedConst { def, args } = uv; + let ty::UnevaluatedConst { def, args, is_rigid } = uv; let args = self.relate_with_variance( ty::Invariant, ty::VarianceDiagInfo::default(), args, args, )?; - Ok(ty::Const::new_unevaluated(self.cx(), ty::UnevaluatedConst { def, args })) + Ok(ty::Const::new_unevaluated( + self.cx(), + ty::UnevaluatedConst { def, args, is_rigid }, + )) } }, ty::ConstKind::Placeholder(placeholder) => { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index cbd6afd68473a..81dbb2e1c1735 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -42,7 +42,8 @@ impl ProcessQueryValue<'_, T> for T { impl<'tcx, T> ProcessQueryValue<'tcx, ty::EarlyBinder<'tcx, T>> for T { #[inline(always)] fn process_decoded(self, _tcx: TyCtxt<'_>, _err: impl Fn() -> !) -> ty::EarlyBinder<'tcx, T> { - ty::EarlyBinder::bind(self) + // FIXME: doubtful. + ty::EarlyBinder::bind_no_rigid_aliases(self) } } diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 2e9cd31a13de0..298fc81b8c33b 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -239,14 +239,17 @@ impl<'tcx> Const<'tcx> { tcx: TyCtxt<'tcx>, def_id: DefId, ) -> ty::EarlyBinder<'tcx, Const<'tcx>> { - ty::EarlyBinder::bind(Const::Unevaluated( - UnevaluatedConst { - def: def_id, - args: ty::GenericArgs::identity_for_item(tcx, def_id), - promoted: None, - }, - tcx.type_of(def_id).skip_binder(), - )) + ty::EarlyBinder::bind( + tcx, + Const::Unevaluated( + UnevaluatedConst { + def: def_id, + args: ty::GenericArgs::identity_for_item(tcx, def_id), + promoted: None, + }, + tcx.type_of(def_id).skip_binder(), + ), + ) } #[inline(always)] @@ -469,7 +472,7 @@ impl<'tcx> UnevaluatedConst<'tcx> { #[inline] pub fn shrink(self) -> ty::UnevaluatedConst<'tcx> { assert_eq!(self.promoted, None); - ty::UnevaluatedConst { def: self.def, args: self.args } + ty::UnevaluatedConst { def: self.def, args: self.args, is_rigid: ty::IsRigid::No } } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 57c2883ef42e4..98757597bb8e9 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -530,8 +530,8 @@ impl<'tcx> Body<'tcx> { /// Returns the return type; it always return first element from `local_decls` array. #[inline] - pub fn bound_return_ty(&self) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { - ty::EarlyBinder::bind(self.local_decls[RETURN_PLACE].ty) + pub fn bound_return_ty(&self, tcx: TyCtxt<'tcx>) -> ty::EarlyBinder<'tcx, Ty<'tcx>> { + ty::EarlyBinder::bind(tcx, self.local_decls[RETURN_PLACE].ty) } /// Gets the location of the terminator for the given block. @@ -624,7 +624,7 @@ impl<'tcx> Body<'tcx> { let mono_literal = instance.instantiate_mir_and_normalize_erasing_regions( tcx, typing_env, - crate::ty::EarlyBinder::bind(constant.const_), + crate::ty::EarlyBinder::bind(tcx, constant.const_), ); mono_literal.try_eval_bits(tcx, typing_env) }; diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index f890c7aadbba5..731f031485c99 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -292,7 +292,7 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef> for AdtDef<'tcx> { self, tcx: TyCtxt<'tcx>, ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { - ty::EarlyBinder::bind( + ty::EarlyBinder::bind_no_rigid_aliases( self.all_fields().map(move |field| tcx.type_of(field.did).skip_binder()), ) } diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index 7f1eeda4ad1d6..a9a930cd002e7 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -379,7 +379,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self, def_id: DefId, ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { - ty::EarlyBinder::bind( + ty::EarlyBinder::bind_no_rigid_aliases( self.predicates_of(def_id) .instantiate_identity(self) .predicates @@ -392,7 +392,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self, def_id: DefId, ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { - ty::EarlyBinder::bind( + ty::EarlyBinder::bind_no_rigid_aliases( self.predicates_of(def_id) .instantiate_own_identity() .map(|(clause, _)| clause.skip_normalization()), @@ -447,7 +447,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self, def_id: DefId, ) -> ty::EarlyBinder<'tcx, impl IntoIterator>>> { - ty::EarlyBinder::bind( + ty::EarlyBinder::bind_no_rigid_aliases( self.const_conditions(def_id) .instantiate_identity(self) .into_iter() @@ -459,7 +459,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self, def_id: DefId, ) -> ty::EarlyBinder<'tcx, impl IntoIterator>>> { - ty::EarlyBinder::bind( + ty::EarlyBinder::bind_no_rigid_aliases( self.explicit_implied_const_bounds(def_id) .iter_identity_copied() .map(Unnormalized::skip_normalization) diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 2945a0be424f8..43512fc45864d 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -3,14 +3,7 @@ pub use rustc_type_ir::fast_reject::*; use super::TyCtxt; -pub type DeepRejectCtxt< - 'tcx, - const INSTANTIATE_LHS_WITH_INFER: bool, - const INSTANTIATE_RHS_WITH_INFER: bool, -> = rustc_type_ir::fast_reject::DeepRejectCtxt< - TyCtxt<'tcx>, - INSTANTIATE_LHS_WITH_INFER, - INSTANTIATE_RHS_WITH_INFER, ->; +pub type DeepRejectCtxt<'tcx, const HANDLE_LHS: u8, const HANDLE_RHS: u8> = + rustc_type_ir::fast_reject::DeepRejectCtxt, HANDLE_LHS, HANDLE_RHS>; pub type SimplifiedType = rustc_type_ir::fast_reject::SimplifiedType; diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 84e0b37a7f7d0..c0a996ed341ba 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -386,10 +386,12 @@ impl<'tcx> GenericPredicates<'tcx> { ) -> impl Iterator>, Span)> + DoubleEndedIterator + ExactSizeIterator { - EarlyBinder::bind(self.predicates).iter_instantiated_copied(tcx, args).map(|u| { - let (clause, span) = u.unzip(); - (clause, span.skip_normalization()) - }) + EarlyBinder::bind_no_rigid_aliases(self.predicates).iter_instantiated_copied(tcx, args).map( + |u| { + let (clause, span) = u.unzip(); + (clause, span.skip_normalization()) + }, + ) } pub fn instantiate_own_identity( @@ -397,7 +399,7 @@ impl<'tcx> GenericPredicates<'tcx> { ) -> impl Iterator>, Span)> + DoubleEndedIterator + ExactSizeIterator { - EarlyBinder::bind(self.predicates).iter_identity_copied().map(|u| { + EarlyBinder::bind_no_rigid_aliases(self.predicates).iter_identity_copied().map(|u| { let (clause, span) = u.unzip(); (clause, span.skip_normalization()) }) @@ -414,7 +416,7 @@ impl<'tcx> GenericPredicates<'tcx> { tcx.predicates_of(def_id).instantiate_into(tcx, instantiated, args); } instantiated.predicates.extend( - self.predicates.iter().map(|(p, _)| EarlyBinder::bind(*p).instantiate(tcx, args)), + self.predicates.iter().map(|(p, _)| EarlyBinder::bind(tcx, *p).instantiate(tcx, args)), ); instantiated.spans.extend(self.predicates.iter().map(|(_, sp)| *sp)); } @@ -466,10 +468,12 @@ impl<'tcx> ConstConditions<'tcx> { ) -> impl Iterator>, Span)> + DoubleEndedIterator + ExactSizeIterator { - EarlyBinder::bind(self.predicates).iter_instantiated_copied(tcx, args).map(|u| { - let (trait_ref, span) = u.unzip(); - (trait_ref, span.skip_normalization()) - }) + EarlyBinder::bind_no_rigid_aliases(self.predicates).iter_instantiated_copied(tcx, args).map( + |u| { + let (trait_ref, span) = u.unzip(); + (trait_ref, span.skip_normalization()) + }, + ) } pub fn instantiate_own_identity( @@ -477,7 +481,7 @@ impl<'tcx> ConstConditions<'tcx> { ) -> impl Iterator>, Span)> + DoubleEndedIterator + ExactSizeIterator { - EarlyBinder::bind(self.predicates).iter_identity_copied().map(|u| { + EarlyBinder::bind_no_rigid_aliases(self.predicates).iter_identity_copied().map(|u| { let (trait_ref, span) = u.unzip(); (trait_ref, span.skip_normalization()) }) @@ -494,7 +498,9 @@ impl<'tcx> ConstConditions<'tcx> { tcx.const_conditions(def_id).instantiate_into(tcx, instantiated, args); } instantiated.extend( - self.predicates.iter().map(|&(p, s)| (EarlyBinder::bind(p).instantiate(tcx, args), s)), + self.predicates + .iter() + .map(|&(p, s)| (EarlyBinder::bind(tcx, p).instantiate(tcx, args), s)), ); } diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index 32625e6b3280e..03a6163b33ade 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -243,7 +243,7 @@ impl<'tcx> InhabitedPredicate<'tcx> { fn instantiate_opt(self, tcx: TyCtxt<'tcx>, args: ty::GenericArgsRef<'tcx>) -> Option { match self { Self::ConstIsZero(c) => { - let c = ty::EarlyBinder::bind(c).instantiate(tcx, args).skip_norm_wip(); + let c = ty::EarlyBinder::bind(tcx, c).instantiate(tcx, args).skip_norm_wip(); let pred = match c.try_to_target_usize(tcx) { Some(0) => Self::True, Some(1..) => Self::False, @@ -252,7 +252,7 @@ impl<'tcx> InhabitedPredicate<'tcx> { Some(pred) } Self::GenericType(t) => Some( - ty::EarlyBinder::bind(t) + ty::EarlyBinder::bind(tcx, t) .instantiate(tcx, args) .skip_norm_wip() .inhabited_predicate(tcx), diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index b81e0b6f3471a..380a047d3d24a 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -855,11 +855,10 @@ impl<'tcx> Instance<'tcx> { self.def.has_polymorphic_mir_body().then_some(self.args) } - pub fn instantiate_mir(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<'tcx, &T>) -> T + pub fn instantiate_mir(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<'tcx, T>) -> T where T: TypeFoldable> + Copy, { - let v = v.map_bound(|v| *v); if let Some(args) = self.args_for_mir_body() { v.instantiate(tcx, args).skip_norm_wip() } else { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 74f9e75fb48c0..618f78d973867 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -910,7 +910,7 @@ impl<'tcx> ProvisionalHiddenType<'tcx> { if cfg!(debug_assertions) && matches!(defining_scope_kind, DefiningScopeKind::HirTypeck) { assert_eq!(result_ty, fold_regions(tcx, result_ty, |_, _| tcx.lifetimes.re_erased)); } - DefinitionSiteHiddenType { span: self.span, ty: ty::EarlyBinder::bind(result_ty) } + DefinitionSiteHiddenType { span: self.span, ty: ty::EarlyBinder::bind(tcx, result_ty) } } } @@ -938,7 +938,7 @@ impl<'tcx> DefinitionSiteHiddenType<'tcx> { pub fn new_error(tcx: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> DefinitionSiteHiddenType<'tcx> { DefinitionSiteHiddenType { span: DUMMY_SP, - ty: ty::EarlyBinder::bind(Ty::new_error(tcx, guar)), + ty: ty::EarlyBinder::bind(tcx, Ty::new_error(tcx, guar)), } } diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 26108f7be6964..7928218876c8e 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -419,7 +419,7 @@ impl<'tcx> Clause<'tcx> { let shifted_pred = tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder()); // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1> - let new = EarlyBinder::bind(shifted_pred) + let new = EarlyBinder::bind(tcx, shifted_pred) .instantiate(tcx, trait_ref.skip_binder().args) .skip_norm_wip(); // 3) ['x] + ['b] -> ['x, 'b] diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index daead99b977c1..4a37d6dea1d2d 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1561,7 +1561,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } match ct.kind() { - ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => { + ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args, .. }) => { match self.tcx().def_kind(def) { DefKind::Const { .. } | DefKind::AssocConst { .. } => { self.pretty_print_value_path(def, args)?; diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 08a8491bab6c5..14275391c366c 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -198,6 +198,7 @@ TrivialLiftImpls! { rustc_hir::Safety, rustc_middle::mir::ConstValue, rustc_type_ir::BoundConstness, + rustc_type_ir::IsRigid, rustc_type_ir::PredicatePolarity, // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 9db9b1769ab9c..a65b816907c7e 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -161,7 +161,7 @@ impl<'tcx> ty::CoroutineArgs> { if tcx.is_async_drop_in_place_coroutine(def_id) { layout.field_tys[*field].ty } else { - ty::EarlyBinder::bind(layout.field_tys[*field].ty) + ty::EarlyBinder::bind(tcx, layout.field_tys[*field].ty) .instantiate(tcx, self.args) .skip_norm_wip() } @@ -523,7 +523,10 @@ impl<'tcx> Ty<'tcx> { #[inline] #[instrument(level = "debug", skip(tcx))] pub fn new_opaque(tcx: TyCtxt<'tcx>, def_id: DefId, args: GenericArgsRef<'tcx>) -> Ty<'tcx> { - Ty::new_alias(tcx, AliasTy::new_from_args(tcx, ty::Opaque { def_id }, args)) + Ty::new_alias( + tcx, + AliasTy::new_from_args(tcx, ty::Opaque { def_id }, args, ty::IsRigid::No), + ) } /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed` @@ -781,7 +784,12 @@ impl<'tcx> Ty<'tcx> { ) -> Ty<'tcx> { Ty::new_alias( tcx, - AliasTy::new_from_args(tcx, ty::Projection { def_id: item_def_id }, args), + AliasTy::new_from_args( + tcx, + ty::Projection { def_id: item_def_id }, + args, + ty::IsRigid::No, + ), ) } @@ -791,7 +799,10 @@ impl<'tcx> Ty<'tcx> { item_def_id: DefId, args: impl IntoIterator>>, ) -> Ty<'tcx> { - Ty::new_alias(tcx, AliasTy::new(tcx, ty::Projection { def_id: item_def_id }, args)) + Ty::new_alias( + tcx, + AliasTy::new(tcx, ty::Projection { def_id: item_def_id }, args, ty::IsRigid::No), + ) } #[inline] diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 99da2da391151..cf8e0ea482201 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1311,8 +1311,14 @@ impl<'tcx> Ty<'tcx> { // query keys used. If normalization fails, we just use `query_ty`. debug_assert!(!typing_env.param_env.has_infer()); let query_ty = tcx - .try_normalize_erasing_regions(typing_env, Unnormalized::new_wip(query_ty)) + .try_normalize_erasing_regions( + typing_env, + Unnormalized::new_wip(ty::reset_rigid_aliases(tcx, query_ty)), + ) .unwrap_or_else(|_| tcx.erase_and_anonymize_regions(query_ty)); + // FIXME: erased region may cause ambiguity. so the alias is not rigid anymore. + // realy dislike this. + let query_ty = ty::reset_rigid_aliases(tcx, query_ty); tcx.needs_drop_raw(typing_env.as_query_input(query_ty)) } diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs index c67d99a8eb7de..6fc3fc6364441 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -72,7 +72,7 @@ pub(crate) fn as_constant_inner<'tcx>( ExprKind::NamedConst { def_id, args, ref user_ty } => { let user_ty = user_ty.as_ref().and_then(push_cuta); if tcx.is_type_const(def_id) { - let uneval = ty::UnevaluatedConst::new(def_id, args); + let uneval = ty::UnevaluatedConst::new(def_id, args, ty::IsRigid::No); let ct = ty::Const::new_unevaluated(tcx, uneval); let const_ = Const::Ty(ty, ct); diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index d59fce3ee0658..dffc9244ca815 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -657,7 +657,10 @@ impl<'tcx, 'ptcx> PatCtxt<'tcx, 'ptcx> { let args = self.typeck_results.node_args(id); // FIXME(mgca): we will need to special case IACs here to have type system compatible // generic args, instead of how we represent them in body expressions. - let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args }); + let c = ty::Const::new_unevaluated( + self.tcx, + ty::UnevaluatedConst::new(def_id, args, ty::IsRigid::No), + ); let mut pattern = self.const_to_pat(c, ty, id, span); // If this is an associated constant with an explicit user-written diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs index 411f090e34921..5dc70366b7b03 100644 --- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs +++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs @@ -245,7 +245,7 @@ pub(crate) fn coroutine_by_move_body_def_id<'tcx>( body_def.explicit_predicates_of(tcx.explicit_predicates_of(coroutine_def_id)); // The type of the coroutine is the `by_move_coroutine_ty`. - body_def.type_of(ty::EarlyBinder::bind(by_move_coroutine_ty)); + body_def.type_of(ty::EarlyBinder::bind(tcx, by_move_coroutine_ty)); body_def.mir_built(tcx.arena.alloc(Steal::new(by_move_body))); diff --git a/compiler/rustc_mir_transform/src/cost_checker.rs b/compiler/rustc_mir_transform/src/cost_checker.rs index 331c98fc198eb..cdd8d8fdc1802 100644 --- a/compiler/rustc_mir_transform/src/cost_checker.rs +++ b/compiler/rustc_mir_transform/src/cost_checker.rs @@ -52,7 +52,7 @@ impl<'b, 'tcx> CostChecker<'b, 'tcx> { fn instantiate_ty(&self, v: Ty<'tcx>) -> Ty<'tcx> { if let Some(instance) = self.instance { - instance.instantiate_mir(self.tcx, ty::EarlyBinder::bind(&v)) + instance.instantiate_mir(self.tcx, ty::EarlyBinder::bind(self.tcx, v)) } else { v } diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index 71c9b79d682df..f2dbfb12e5757 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -83,7 +83,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { // If the inner type matches the type bound by `Pointer` if inner_ty == bound_ty { // Do an instantiation using the parameters from the callsite - let instantiated_ty = EarlyBinder::bind(inner_ty) + let instantiated_ty = EarlyBinder::bind(self.tcx, inner_ty) .instantiate(self.tcx, args_ref) .skip_norm_wip(); if let Some((fn_id, fn_args)) = diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 31871c62fa7a2..464f2eb784400 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -425,9 +425,10 @@ impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> { work_list.push(target); // If the place doesn't actually need dropping, treat it like a regular goto. - let ty = callsite - .callee - .instantiate_mir(tcx, ty::EarlyBinder::bind(&place.ty(callee_body, tcx).ty)); + let ty = callsite.callee.instantiate_mir( + tcx, + ty::EarlyBinder::bind(tcx, place.ty(callee_body, tcx).ty), + ); if ty.needs_drop(tcx, self.typing_env()) && let UnwindAction::Cleanup(unwind) = unwind { @@ -631,7 +632,7 @@ fn try_inlining<'tcx, I: Inliner<'tcx>>( let Ok(callee_body) = callsite.callee.try_instantiate_mir_and_normalize_erasing_regions( tcx, inliner.typing_env(), - ty::EarlyBinder::bind(callee_body.clone()), + ty::EarlyBinder::bind(tcx, callee_body.clone()), ) else { debug!("failed to normalize callee body"); return Err("implementation limitation -- could not normalize callee body"); diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index 9d031b6548021..7d135d963134d 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -76,7 +76,7 @@ fn process<'tcx>( let Ok(args) = caller.try_instantiate_mir_and_normalize_erasing_regions( tcx, typing_env, - ty::EarlyBinder::bind(args), + ty::EarlyBinder::bind(tcx, args), ) else { trace!(?caller, ?typing_env, ?args, "cannot normalize, skipping"); continue; diff --git a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs index 776840a6fe8b2..62bf27f7a96ce 100644 --- a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs +++ b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs @@ -63,10 +63,10 @@ impl<'tcx> MutVisitor<'tcx> for PostAnalysisNormalizeVisitor<'tcx> { // We have to use `try_normalize_erasing_regions` here, since it's // possible that we visit impossible-to-satisfy where clauses here, // see #91745 - if let Ok(c) = self - .tcx - .try_normalize_erasing_regions(self.typing_env, Unnormalized::new_wip(constant.const_)) - { + if let Ok(c) = self.tcx.try_normalize_erasing_regions( + self.typing_env, + Unnormalized::new_wip(ty::reset_rigid_aliases(self.tcx, constant.const_)), + ) { constant.const_ = c; } self.super_const_operand(constant, location); @@ -77,9 +77,10 @@ impl<'tcx> MutVisitor<'tcx> for PostAnalysisNormalizeVisitor<'tcx> { // We have to use `try_normalize_erasing_regions` here, since it's // possible that we visit impossible-to-satisfy where clauses here, // see #91745 - if let Ok(t) = - self.tcx.try_normalize_erasing_regions(self.typing_env, Unnormalized::new_wip(*ty)) - { + if let Ok(t) = self.tcx.try_normalize_erasing_regions( + self.typing_env, + Unnormalized::new_wip(ty::reset_rigid_aliases(self.tcx, *ty)), + ) { *ty = t; } } diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 7f92199dec455..ba07361a7b571 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -142,7 +142,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body< }; let mut body = - EarlyBinder::bind(body.clone()).instantiate(tcx, args).skip_norm_wip(); + EarlyBinder::bind(tcx, body.clone()).instantiate(tcx, args).skip_norm_wip(); debug!("make_shim({:?}) = {:?}", instance, body); pm::run_passes( diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index 3a0d0ce474d77..197e448c87f34 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -20,7 +20,8 @@ pub(super) fn build_async_destructor_ctor_shim<'tcx>( debug_assert_eq!(Some(def_id), tcx.lang_items().async_drop_in_place_fn()); let generic_body = tcx.optimized_mir(def_id); let args = tcx.mk_args(&[ty.into()]); - let mut body = EarlyBinder::bind(generic_body.clone()).instantiate(tcx, args).skip_norm_wip(); + let mut body = + EarlyBinder::bind(tcx, generic_body.clone()).instantiate(tcx, args).skip_norm_wip(); // Minimal shim passes except MentionedItems, // it causes error "mentioned_items for DefId(...async_drop_in_place...) have already been set @@ -206,7 +207,7 @@ fn build_adrop_for_coroutine_shim<'tcx>( // Replace old _1.0 accesses into _x accesses; let body = tcx.optimized_mir(*coroutine_def_id).future_drop_poll().unwrap(); let mut body: Body<'tcx> = - EarlyBinder::bind(body.clone()).instantiate(tcx, impl_args).skip_norm_wip(); + EarlyBinder::bind(tcx, body.clone()).instantiate(tcx, impl_args).skip_norm_wip(); body.source.instance = instance; body.phase = MirPhase::Runtime(RuntimePhase::Initial); body.var_debug_info.clear(); diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 815b94dc510e8..9fa8545df6c5f 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -777,7 +777,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { return; }; - ty::EarlyBinder::bind(f_ty.ty) + ty::EarlyBinder::bind(self.tcx, f_ty.ty) .instantiate(self.tcx, args) .skip_norm_wip() } else { diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 9ddd33678c341..e09aa6d0f248e 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -633,7 +633,7 @@ fn check_normalization_error<'tcx>( match self.instance.try_instantiate_mir_and_normalize_erasing_regions( self.tcx, ty::TypingEnv::fully_monomorphized(), - ty::EarlyBinder::bind(t), + ty::EarlyBinder::bind(self.tcx, t), ) { Ok(_) => ControlFlow::Continue(()), Err(_) => ControlFlow::Break(()), @@ -697,7 +697,7 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { self.instance.instantiate_mir_and_normalize_erasing_regions( self.tcx, ty::TypingEnv::fully_monomorphized(), - ty::EarlyBinder::bind(value), + ty::EarlyBinder::bind(self.tcx, value), ) } diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs index 10218523ca232..142bef3ec06c0 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs @@ -245,7 +245,7 @@ fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &m let callee_ty = instance.instantiate_mir_and_normalize_erasing_regions( tcx, ty::TypingEnv::fully_monomorphized(), - ty::EarlyBinder::bind(callee_ty), + ty::EarlyBinder::bind(tcx, callee_ty), ); check_call_site_abi(tcx, callee_ty, body.source.instance, || { let loc = Location { diff --git a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs index a24b0443d39c9..4ec9f4b807ec2 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/move_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/move_check.rs @@ -60,7 +60,7 @@ impl<'tcx> MoveCheckVisitor<'tcx> { self.instance.instantiate_mir_and_normalize_erasing_regions( self.tcx, ty::TypingEnv::fully_monomorphized(), - ty::EarlyBinder::bind(value), + ty::EarlyBinder::bind(self.tcx, value), ) } diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs index 6fcb18177a142..bf24662e1e48a 100644 --- a/compiler/rustc_monomorphize/src/util.rs +++ b/compiler/rustc_monomorphize/src/util.rs @@ -30,12 +30,12 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In let before_feature_tys = tcx.instantiate_and_normalize_erasing_regions( closure_instance.args, typing_env, - ty::EarlyBinder::bind(before_feature_tys), + ty::EarlyBinder::bind(tcx, before_feature_tys), ); let after_feature_tys = tcx.instantiate_and_normalize_erasing_regions( closure_instance.args, typing_env, - ty::EarlyBinder::bind(after_feature_tys), + ty::EarlyBinder::bind(tcx, after_feature_tys), ); let new_size = tcx diff --git a/compiler/rustc_next_trait_solver/src/normalize.rs b/compiler/rustc_next_trait_solver/src/normalize.rs index 7506591d6fb5d..035073d5ca27c 100644 --- a/compiler/rustc_next_trait_solver/src/normalize.rs +++ b/compiler/rustc_next_trait_solver/src/normalize.rs @@ -1,9 +1,11 @@ +use std::fmt::Debug; + +use rustc_data_structures::sso::{SsoHashMap, SsoHashSet}; use rustc_type_ir::data_structures::ensure_sufficient_stack; use rustc_type_ir::inherent::*; -use rustc_type_ir::solve::{Goal, NoSolution}; use rustc_type_ir::{ - self as ty, Binder, FallibleTypeFolder, InferConst, InferCtxtLike, InferTy, Interner, - TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, + self as ty, AliasTerm, Binder, FallibleTypeFolder, InferConst, InferCtxtLike, InferTy, + Interner, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, UniverseIndex, }; use tracing::instrument; @@ -13,7 +15,7 @@ use crate::placeholder::{BoundVarReplacer, PlaceholderReplacer}; /// This folder normalizes value and collects ambiguous goals. /// /// Note that for ambiguous alias which contains escaping bound vars, -/// we just return the original alias and don't collect the ambiguous goal. +/// we just return the original alias. pub struct NormalizationFolder<'a, Infcx, I, F> where Infcx: InferCtxtLike, @@ -21,11 +23,17 @@ where { infcx: &'a Infcx, universes: Vec>, - stalled_goals: Vec>, normalize: F, + cache: SsoHashMap, +} + +#[derive(PartialEq, Eq, Debug)] +pub enum NormalizationWasAmbiguous { + Yes, + No, } -#[derive(PartialEq, Eq)] +#[derive(PartialEq, Eq, Debug)] enum HasEscapingBoundVars { Yes, No, @@ -39,6 +47,7 @@ where { infcx: &'a Infcx, max_universe: ty::UniverseIndex, + cache: SsoHashSet, } impl<'a, Infcx, I> MaxUniverse<'a, Infcx, I> @@ -47,7 +56,7 @@ where I: Interner, { fn new(infcx: &'a Infcx) -> Self { - MaxUniverse { infcx, max_universe: ty::UniverseIndex::ROOT } + MaxUniverse { infcx, max_universe: ty::UniverseIndex::ROOT, cache: Default::default() } } fn max_universe(self) -> ty::UniverseIndex { @@ -73,7 +82,9 @@ where self.max_universe = self.max_universe.max(self.infcx.universe_of_ty(vid).unwrap()); } - t.super_visit_with(self) + if self.cache.insert(t) { + t.super_visit_with(self) + } } fn visit_const(&mut self, c: I::Const) { @@ -97,34 +108,25 @@ where } } -impl<'a, Infcx, I, F> NormalizationFolder<'a, Infcx, I, F> +impl<'a, Infcx, I, F, E> NormalizationFolder<'a, Infcx, I, F> where Infcx: InferCtxtLike, I: Interner, - F: FnMut(I::Term) -> Result<(I::Term, Option>), NoSolution>, + F: FnMut(AliasTerm) -> Result<(I::Term, NormalizationWasAmbiguous), E>, { - pub fn new( - infcx: &'a Infcx, - universes: Vec>, - stalled_goals: Vec>, - normalize: F, - ) -> Self { - Self { infcx, universes, stalled_goals, normalize } - } - - pub fn stalled_goals(self) -> Vec> { - self.stalled_goals + pub fn new(infcx: &'a Infcx, universes: Vec>, normalize: F) -> Self { + Self { infcx, universes, normalize, cache: Default::default() } } fn normalize_alias_term( &mut self, - alias_term: I::Term, + alias_term: AliasTerm, has_escaping: HasEscapingBoundVars, - ) -> Result { + ) -> Result, E> { let current_universe = self.infcx.universe(); self.infcx.create_next_universe(); - let (normalized, ambig_goal) = (self.normalize)(alias_term)?; + let (normalized, normalization_was_ambiguous) = (self.normalize)(alias_term)?; // Return ambiguous higher ranked alias as is, if // - it contains escaping vars, and @@ -134,27 +136,29 @@ where // referencing the temporary placeholders. // // We can normalize the ambiguous alias again after the binder is instantiated. - if ambig_goal.is_some() && has_escaping == HasEscapingBoundVars::Yes { + if NormalizationWasAmbiguous::Yes == normalization_was_ambiguous + && has_escaping == HasEscapingBoundVars::Yes + { let mut visitor = MaxUniverse::new(self.infcx); normalized.visit_with(&mut visitor); let max_universe = visitor.max_universe(); if current_universe.cannot_name(max_universe) { - return Ok(alias_term); + return Ok(None); } } - self.stalled_goals.extend(ambig_goal); - Ok(normalized) + Ok(Some(normalized)) } } -impl<'a, Infcx, I, F> FallibleTypeFolder for NormalizationFolder<'a, Infcx, I, F> +impl<'a, Infcx, I, F, E> FallibleTypeFolder for NormalizationFolder<'a, Infcx, I, F> where Infcx: InferCtxtLike, I: Interner, - F: FnMut(I::Term) -> Result<(I::Term, Option>), NoSolution>, + F: FnMut(AliasTerm) -> Result<(I::Term, NormalizationWasAmbiguous), E>, + E: Debug, { - type Error = NoSolution; + type Error = E; fn cx(&self) -> I { self.infcx.cx() @@ -173,70 +177,120 @@ where #[instrument(level = "trace", skip(self), ret)] fn try_fold_ty(&mut self, ty: I::Ty) -> Result { let infcx = self.infcx; - if !ty.has_aliases() { - return Ok(ty); + + // TODO: detct typing env change. + // if !ty.has_non_rigid_aliases() { + // return Ok(ty); + // } + + if let Some(ty) = self.cache.get(&ty) { + return Ok(*ty); } + // No need to renormalize if the alias is already rigid. + // Note rigid opaque type in `PostAnalysis` mode can invalidate other rigid aliases + // as well if it's in param env. + // if let ty::Alias(alias) = ty.kind() + // && alias.is_rigid == ty::IsRigid::Yes + // { + // // We shouldn't allow rigid alias contains non-rigid types. + // debug_assert!(!alias.has_non_rigid_aliases()); + // // FIXME: can we leak rigid opaque into its defining scope? via typing mode change? + // debug_assert!( + // !(ty.has_opaque_types() + // && matches!(infcx.typing_mode_raw(), TypingMode::PostAnalysis)) + // ); + // return Ok(ty); + // } // With eager normalization, we should normalize the args of alias before // normalizing the alias itself. - let ty = ty.try_super_fold_with(self)?; - let ty::Alias(..) = ty.kind() else { return Ok(ty) }; - - if ty.has_escaping_bound_vars() { - let (ty, mapped_regions, mapped_types, mapped_consts) = - BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ty); - let result = ensure_sufficient_stack(|| { - self.normalize_alias_term(ty.into(), HasEscapingBoundVars::Yes) - })? - .expect_ty(); - Ok(PlaceholderReplacer::replace_placeholders( - infcx, - mapped_regions, - mapped_types, - mapped_consts, - &self.universes, - result, - )) + let folded_ty = ty.try_super_fold_with(self)?; + let ty::Alias(alias_ty) = folded_ty.kind() else { return Ok(folded_ty) }; + + let result = if alias_ty.has_escaping_bound_vars() { + let (alias_ty, mapped_regions, mapped_types, mapped_consts) = + BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, alias_ty); + match ensure_sufficient_stack(|| { + self.normalize_alias_term(alias_ty.into(), HasEscapingBoundVars::Yes) + })? { + Some(result) => PlaceholderReplacer::replace_placeholders( + infcx, + mapped_regions, + mapped_types, + mapped_consts, + &self.universes, + result.expect_ty(), + ), + None => folded_ty, + } } else { - Ok(ensure_sufficient_stack(|| { - self.normalize_alias_term(ty.into(), HasEscapingBoundVars::No) - })? - .expect_ty()) + match ensure_sufficient_stack(|| { + self.normalize_alias_term(alias_ty.into(), HasEscapingBoundVars::No) + })? { + Some(term) => term.expect_ty(), + None => folded_ty, + } + }; + + assert!(self.cache.insert(ty, result).is_none(), "{ty:?} {result:?} {:?}", self.cache); + + if let ty::Alias(alias) = ty.kind() + && alias.is_rigid == ty::IsRigid::Yes + { + // find out missing typing env change. + let original = crate::resolve::eager_resolve_vars_with_infcx(infcx, ty); + let normalized = crate::resolve::eager_resolve_vars_with_infcx(infcx, result); + debug_assert_eq!(original, normalized); } + Ok(result) } #[instrument(level = "trace", skip(self), ret)] fn try_fold_const(&mut self, ct: I::Const) -> Result { let infcx = self.infcx; - if !ct.has_aliases() { - return Ok(ct); - } + // TODO: detect typing env change. + // if !ct.has_non_rigid_aliases() { + // return Ok(ct); + // } // With eager normalization, we should normalize the args of alias before // normalizing the alias itself. let ct = ct.try_super_fold_with(self)?; - let ty::ConstKind::Unevaluated(..) = ct.kind() else { return Ok(ct) }; + let ty::ConstKind::Unevaluated(uv) = ct.kind() else { return Ok(ct) }; if ct.has_escaping_bound_vars() { - let (ct, mapped_regions, mapped_types, mapped_consts) = - BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, ct); - let result = ensure_sufficient_stack(|| { - self.normalize_alias_term(ct.into(), HasEscapingBoundVars::Yes) - })? - .expect_const(); - Ok(PlaceholderReplacer::replace_placeholders( - infcx, - mapped_regions, - mapped_types, - mapped_consts, - &self.universes, - result, - )) + let (uv, mapped_regions, mapped_types, mapped_consts) = + BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, uv); + match ensure_sufficient_stack(|| { + self.normalize_alias_term( + AliasTerm::from_unevaluated_const(infcx.cx(), uv), + HasEscapingBoundVars::Yes, + ) + })? { + Some(result) => Ok(PlaceholderReplacer::replace_placeholders( + infcx, + mapped_regions, + mapped_types, + mapped_consts, + &self.universes, + result.expect_const(), + )), + None => Ok(ct), + } } else { - Ok(ensure_sufficient_stack(|| { - self.normalize_alias_term(ct.into(), HasEscapingBoundVars::No) - })? - .expect_const()) + match ensure_sufficient_stack(|| { + self.normalize_alias_term( + AliasTerm::from_unevaluated_const(infcx.cx(), uv), + HasEscapingBoundVars::No, + ) + })? { + Some(term) => Ok(term.expect_const()), + None => Ok(ct), + } } } + + fn try_fold_predicate(&mut self, p: I::Predicate) -> Result { + if p.allow_normalization() { p.try_super_fold_with(self) } else { Ok(p) } + } } diff --git a/compiler/rustc_next_trait_solver/src/resolve.rs b/compiler/rustc_next_trait_solver/src/resolve.rs index c3c57eccd6eff..344c21acbca8b 100644 --- a/compiler/rustc_next_trait_solver/src/resolve.rs +++ b/compiler/rustc_next_trait_solver/src/resolve.rs @@ -11,9 +11,9 @@ use crate::delegate::SolverDelegate; // EAGER RESOLUTION /// Resolves ty, region, and const vars to their inferred values or their root vars. -struct EagerResolver<'a, D, I = ::Interner> +struct EagerResolver<'a, D, I = ::Interner> where - D: SolverDelegate, + D: InferCtxtLike, I: Interner, { delegate: &'a D, @@ -25,6 +25,13 @@ where pub fn eager_resolve_vars>( delegate: &D, value: T, +) -> T { + eager_resolve_vars_with_infcx(&**delegate, value) +} + +pub fn eager_resolve_vars_with_infcx>( + delegate: &D, + value: T, ) -> T { if value.has_infer() { let mut folder = EagerResolver::new(delegate); @@ -34,13 +41,13 @@ pub fn eager_resolve_vars>( } } -impl<'a, D: SolverDelegate> EagerResolver<'a, D> { +impl<'a, D: InferCtxtLike> EagerResolver<'a, D> { fn new(delegate: &'a D) -> Self { EagerResolver { delegate, cache: Default::default() } } } -impl, I: Interner> TypeFolder for EagerResolver<'_, D> { +impl, I: Interner> TypeFolder for EagerResolver<'_, D> { fn cx(&self) -> I { self.delegate.cx() } diff --git a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs index 47d33985f9d36..ecab1b9a52fd0 100644 --- a/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs +++ b/compiler/rustc_next_trait_solver/src/solve/alias_relate.rs @@ -53,7 +53,7 @@ where self.add_goal( GoalSource::TypeRelating, goal.with(cx, ty::NormalizesTo { alias, term }), - ); + )?; term } else { lhs @@ -65,7 +65,7 @@ where self.add_goal( GoalSource::TypeRelating, goal.with(cx, ty::NormalizesTo { alias, term }), - ); + )?; term } else { rhs @@ -94,10 +94,12 @@ where } (Some(alias), None) => { + debug_assert_eq!(alias.is_rigid, ty::IsRigid::Yes); self.relate_rigid_alias_non_alias(param_env, alias, variance, rhs)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } (None, Some(alias)) => { + debug_assert_eq!(alias.is_rigid, ty::IsRigid::Yes); self.relate_rigid_alias_non_alias( param_env, alias, diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 7f3627c6db54e..1983ff2b996ea 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -68,7 +68,7 @@ where ) -> Result, NoSolutionOrRerunNonErased> { Self::probe_and_match_goal_against_assumption(ecx, parent_source, goal, assumption, |ecx| { for (nested_source, goal) in requirements { - ecx.add_goal(nested_source, goal); + ecx.add_goal(nested_source, goal)?; } ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) @@ -113,7 +113,7 @@ where bounds, ) { Ok(requirements) => { - ecx.add_goals(GoalSource::ImplWhereBound, requirements); + ecx.add_goals(GoalSource::ImplWhereBound, requirements)?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } Err(_) => { @@ -137,7 +137,7 @@ where goal: Goal, assumption: I::Clause, ) -> Result, CandidateHeadUsages>, RerunNonErased> { - match Self::fast_reject_assumption(ecx, goal, assumption) { + match Self::fast_reject_param_env(ecx, goal, assumption) { Ok(()) => {} Err(NoSolution) => return Ok(Err(CandidateHeadUsages::default())), } @@ -193,6 +193,12 @@ where .enter(|ecx| Self::match_assumption(ecx, goal, assumption, then)) } + fn fast_reject_param_env( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + assumption: I::Clause, + ) -> Result<(), NoSolution>; + /// Try to reject the assumption based off of simple heuristics, such as [`ty::ClauseKind`] /// and `DefId`. fn fast_reject_assumption( @@ -966,7 +972,7 @@ where elaborate::elaborate(cx, [predicate]) .skip(1) .map(|predicate| goal.with(cx, predicate)), - ); + )?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } }) diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index d6ddd9fec7c08..70fd29f5d6080 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -39,6 +39,25 @@ where self.def_id() } + fn fast_reject_param_env( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + assumption: I::Clause, + ) -> Result<(), NoSolution> { + if let Some(host_clause) = assumption.as_host_effect_clause() + && host_clause.def_id() == goal.predicate.def_id() + && host_clause.constness().satisfies(goal.predicate.constness) + && DeepRejectCtxt::relate_fully_normalized(ecx.cx()).args_may_unify( + goal.predicate.trait_ref.args, + host_clause.skip_binder().trait_ref.args, + ) + { + Ok(()) + } else { + Err(NoSolution) + } + } + fn fast_reject_assumption( ecx: &mut EvalCtxt<'_, D>, goal: Goal, @@ -117,7 +136,7 @@ where .skip_norm_wip(), ) }), - ); + )?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }, )); @@ -169,7 +188,7 @@ where .iter_instantiated(cx, impl_args) .map(Unnormalized::skip_norm_wip) .map(|pred| goal.with(cx, pred)); - ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds); + ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds)?; // For this impl to be `const`, we need to check its `[const]` bounds too. let const_conditions = cx @@ -183,7 +202,7 @@ where .skip_norm_wip(), ) }); - ecx.add_goals(GoalSource::ImplWhereBound, const_conditions); + ecx.add_goals(GoalSource::ImplWhereBound, const_conditions)?; then(ecx, certainty) }) @@ -234,8 +253,8 @@ where // `GoalSource::ImplWhereClause` here would be incorrect, as we also // impl them, which means we're "stepping out of the impl constructor" // again. To handle this, we treat these cycles as ambiguous for now. - ecx.add_goals(GoalSource::Misc, where_clause_bounds); - ecx.add_goals(GoalSource::Misc, const_conditions); + ecx.add_goals(GoalSource::Misc, where_clause_bounds)?; + ecx.add_goals(GoalSource::Misc, const_conditions)?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -270,8 +289,8 @@ where ), ) }), - ); - }); + ) + })?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) @@ -424,7 +443,7 @@ where .to_host_effect_clause(cx, goal.predicate.constness), ) }), - ); + )?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 54d306466cf5b..d3e322bc51627 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -3,7 +3,7 @@ use std::ops::ControlFlow; #[cfg(feature = "nightly")] use rustc_macros::StableHash; -use rustc_type_ir::data_structures::{HashMap, HashSet}; +use rustc_type_ir::data_structures::HashSet; use rustc_type_ir::inherent::*; use rustc_type_ir::region_constraint::RegionConstraint; use rustc_type_ir::relate::Relate; @@ -15,9 +15,9 @@ use rustc_type_ir::solve::{ RerunNonErased, RerunReason, RerunResultExt, SmallCopyList, }; use rustc_type_ir::{ - self as ty, CanonicalVarValues, ClauseKind, InferCtxtLike, Interner, MayBeErased, - OpaqueTypeKey, PredicateKind, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, - TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, + self as ty, AliasRelationDirection, AliasTermKind, CanonicalVarValues, ClauseKind, + InferCtxtLike, Interner, MayBeErased, OpaqueTypeKey, PredicateKind, TypeFoldable, + TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, }; use tracing::{Level, debug, instrument, trace, warn}; @@ -28,6 +28,7 @@ use crate::canonical::{ }; use crate::coherence; use crate::delegate::SolverDelegate; +use crate::normalize::{NormalizationFolder, NormalizationWasAmbiguous}; use crate::placeholder::BoundVarReplacer; use crate::resolve::eager_resolve_vars; use crate::solve::search_graph::SearchGraph; @@ -308,18 +309,10 @@ where // We currently only consider a cycle coinductive if it steps // into a where-clause of a coinductive trait. CurrentGoalKind::CoinductiveTrait => PathKind::Coinductive, - // While normalizing via an impl does step into a where-clause of - // an impl, accessing the associated item immediately steps out of - // it again. This means cycles/recursive calls are not guarded - // by impls used for normalization. - // - // See tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.rs - // for how this can go wrong. - CurrentGoalKind::NormalizesTo => PathKind::Inductive, // We probably want to make all traits coinductive in the future, // so we treat cycles involving where-clauses of not-yet coinductive // traits as ambiguous for now. - CurrentGoalKind::Misc => PathKind::Unknown, + CurrentGoalKind::NormalizesTo | CurrentGoalKind::Misc => PathKind::Unknown, }, // Relating types is always unproductive. If we were to map proof trees to // corecursive functions as explained in #136824, relating types never @@ -1029,11 +1022,19 @@ where } #[instrument(level = "debug", skip(self))] - pub(super) fn add_goal(&mut self, source: GoalSource, mut goal: Goal) { - goal.predicate = - goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(self, source, goal.param_env)); + pub(super) fn add_goal( + &mut self, + source: GoalSource, + mut goal: Goal, + ) -> Result<(), NoSolutionOrRerunNonErased> { + goal.predicate = self.normalize( + GoalSource::NormalizeGoal(self.step_kind_for_source(source)), + goal.param_env, + goal.predicate, + )?; self.inspect.add_goal(self.delegate, self.max_input_universe, source, goal); self.nested_goals.push((source, goal, None)); + Ok(()) } #[instrument(level = "trace", skip(self, goals))] @@ -1041,10 +1042,11 @@ where &mut self, source: GoalSource, goals: impl IntoIterator>, - ) { + ) -> Result<(), NoSolutionOrRerunNonErased> { for goal in goals { - self.add_goal(source, goal); + self.add_goal(source, goal)?; } + Ok(()) } pub(super) fn next_region_var(&mut self) -> I::Region { @@ -1074,6 +1076,19 @@ where } } + pub(super) fn next_infer_for_alias(&mut self, alias: ty::AliasTerm) -> I::Term { + match alias.kind(self.cx()) { + AliasTermKind::ProjectionTy { .. } + | AliasTermKind::InherentTy { .. } + | AliasTermKind::OpaqueTy { .. } + | AliasTermKind::FreeTy { .. } => self.next_ty_infer().into(), + AliasTermKind::UnevaluatedConst { .. } + | AliasTermKind::ProjectionConst { .. } + | AliasTermKind::FreeConst { .. } + | AliasTermKind::InherentConst { .. } => self.next_const_infer().into(), + } + } + /// Is the projection predicate is of the form `exists ::Assoc = T`. /// /// This is the case if the `term` does not occur in any other part of the predicate @@ -1207,7 +1222,7 @@ where param_env: I::ParamEnv, lhs: T, rhs: T, - ) -> Result<(), NoSolution> { + ) -> Result<(), NoSolutionOrRerunNonErased> { self.relate(param_env, lhs, ty::Variance::Invariant, rhs) } @@ -1223,7 +1238,7 @@ where alias: ty::AliasTerm, variance: ty::Variance, term: I::Term, - ) -> Result<(), NoSolution> { + ) -> Result<(), NoSolutionOrRerunNonErased> { // NOTE: this check is purely an optimization, the structural eq would // always fail if the term is not an inference variable. if term.is_infer() { @@ -1248,7 +1263,7 @@ where debug_assert!(obligations.is_empty()); self.relate(param_env, alias, variance, rigid_ctor) } else { - Err(NoSolution) + Err(NoSolutionOrRerunNonErased::NoSolution(NoSolution)) } } @@ -1261,7 +1276,7 @@ where param_env: I::ParamEnv, lhs: T, rhs: T, - ) -> Result<(), NoSolution> { + ) -> Result<(), NoSolutionOrRerunNonErased> { let result = self.delegate.eq_structurally_relating_aliases( param_env, lhs, @@ -1278,7 +1293,7 @@ where param_env: I::ParamEnv, sub: T, sup: T, - ) -> Result<(), NoSolution> { + ) -> Result<(), NoSolutionOrRerunNonErased> { self.relate(param_env, sub, ty::Variance::Covariant, sup) } @@ -1289,7 +1304,7 @@ where lhs: T, variance: ty::Variance, rhs: T, - ) -> Result<(), NoSolution> { + ) -> Result<(), NoSolutionOrRerunNonErased> { let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?; for &goal in goals.iter() { let source = match goal.predicate.kind().skip_binder() { @@ -1300,7 +1315,7 @@ where ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => GoalSource::Misc, p => unreachable!("unexpected nested goal in `relate`: {p:?}"), }; - self.add_goal(source, goal); + self.add_goal(source, goal)?; } Ok(()) } @@ -1441,7 +1456,7 @@ where opaque_args: I::GenericArgs, param_env: I::ParamEnv, hidden_ty: I::Ty, - ) { + ) -> Result<(), NoSolutionOrRerunNonErased> { let mut goals = Vec::new(); self.delegate.add_item_bounds_for_hidden_type( opaque_def_id, @@ -1450,7 +1465,8 @@ where hidden_ty, &mut goals, ); - self.add_goals(GoalSource::AliasWellFormed, goals); + self.add_goals(GoalSource::AliasWellFormed, goals)?; + Ok(()) } // Try to evaluate a const, or return `None` if the const is too generic. @@ -1731,112 +1747,44 @@ where ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals } } -} -/// Eagerly replace aliases with inference variables, emitting `AliasRelate` -/// goals, used when adding goals to the `EvalCtxt`. We compute the -/// `AliasRelate` goals before evaluating the actual goal to get all the -/// constraints we can. -/// -/// This is a performance optimization to more eagerly detect cycles during trait -/// solving. See tests/ui/traits/next-solver/cycles/cycle-modulo-ambig-aliases.rs. -/// -/// The emitted goals get evaluated in the context of the parent goal; by -/// replacing aliases in nested goals we essentially pull the normalization out of -/// the nested goal. We want to treat the goal as if the normalization still happens -/// inside of the nested goal by inheriting the `step_kind` of the nested goal and -/// storing it in the `GoalSource` of the emitted `AliasRelate` goals. -/// This is necessary for tests/ui/sized/coinductive-1.rs to compile. -struct ReplaceAliasWithInfer<'me, 'a, D, I> -where - D: SolverDelegate, - I: Interner, -{ - ecx: &'me mut EvalCtxt<'a, D>, - param_env: I::ParamEnv, - normalization_goal_source: GoalSource, - cache: HashMap, -} - -impl<'me, 'a, D, I> ReplaceAliasWithInfer<'me, 'a, D, I> -where - D: SolverDelegate, - I: Interner, -{ - fn new( - ecx: &'me mut EvalCtxt<'a, D>, - for_goal_source: GoalSource, + pub(super) fn normalize>( + &mut self, + source: GoalSource, param_env: I::ParamEnv, - ) -> Self { - let step_kind = ecx.step_kind_for_source(for_goal_source); - ReplaceAliasWithInfer { - ecx, - param_env, - normalization_goal_source: GoalSource::NormalizeGoal(step_kind), - cache: Default::default(), - } - } -} - -impl TypeFolder for ReplaceAliasWithInfer<'_, '_, D, I> -where - D: SolverDelegate, - I: Interner, -{ - fn cx(&self) -> I { - self.ecx.cx() - } - - fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { - match ty.kind() { - ty::Alias(..) if !ty.has_escaping_bound_vars() => { - let infer_ty = self.ecx.next_ty_infer(); - let normalizes_to = ty::PredicateKind::AliasRelate( - ty.into(), - infer_ty.into(), - ty::AliasRelationDirection::Equate, - ); - self.ecx.add_goal( - self.normalization_goal_source, - Goal::new(self.cx(), self.param_env, normalizes_to), - ); - infer_ty - } - _ => { - if !ty.has_aliases() { - ty - } else if let Some(&entry) = self.cache.get(&ty) { - return entry; - } else { - let res = ty.super_fold_with(self); - assert!(self.cache.insert(ty, res).is_none()); - res + value: T, + ) -> Result { + let value = self.delegate.resolve_vars_if_possible(value); + + // TODO: detect all typing env change. + // if !value.has_non_rigid_aliases() { + // return Ok(value); + // } + + // To drop the mutable borrow of self early. + let infcx = self.delegate.deref(); + let mut folder = NormalizationFolder::new(infcx, vec![], |alias_term| { + let infer_term = self.next_infer_for_alias(alias_term); + let pred = ty::PredicateKind::AliasRelate( + alias_term.to_term(infcx.cx()), + infer_term.into(), + AliasRelationDirection::Equate, + ); + let goal = Goal::new(self.cx(), param_env, pred); + self.inspect.add_goal(self.delegate, self.max_input_universe, source, goal); + let GoalEvaluation { goal, certainty, has_changed: _, stalled_on } = + self.evaluate_goal(source, goal, None)?; + let normalization_was_ambiguous = match certainty { + Certainty::Yes => NormalizationWasAmbiguous::No, + Certainty::Maybe(_) => { + self.nested_goals.push((source, goal, stalled_on)); + NormalizationWasAmbiguous::Yes } - } - } - } - - fn fold_const(&mut self, ct: I::Const) -> I::Const { - match ct.kind() { - ty::ConstKind::Unevaluated(..) if !ct.has_escaping_bound_vars() => { - let infer_ct = self.ecx.next_const_infer(); - let normalizes_to = ty::PredicateKind::AliasRelate( - ct.into(), - infer_ct.into(), - ty::AliasRelationDirection::Equate, - ); - self.ecx.add_goal( - self.normalization_goal_source, - Goal::new(self.cx(), self.param_env, normalizes_to), - ); - infer_ct - } - _ => ct.super_fold_with(self), - } - } + }; - fn fold_predicate(&mut self, predicate: I::Predicate) -> I::Predicate { - if predicate.allow_normalization() { predicate.super_fold_with(self) } else { predicate } + Ok((self.resolve_vars_if_possible(infer_term), normalization_was_ambiguous)) + }); + value.try_fold_with(&mut folder) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index fbd6bdfa0a989..ccfc16403d066 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -171,7 +171,7 @@ where ) -> QueryResultOrRerunNonErased { match self.well_formed_goals(goal.param_env, goal.predicate) { Some(goals) => { - self.add_goals(GoalSource::Misc, goals); + self.add_goals(GoalSource::Misc, goals)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } None => self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS), @@ -381,7 +381,7 @@ where ); // We normalize the self type to be able to relate it with // types from candidates. - self.add_goal(GoalSource::TypeRelating, alias_relate_goal); + self.add_goal(GoalSource::TypeRelating, alias_relate_goal)?; self.try_evaluate_added_goals()?; Ok(self.resolve_vars_if_possible(normalized_term)) } else { diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs index d68c7dd11d1d9..027da2b34d734 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs @@ -29,17 +29,24 @@ where .iter_instantiated(cx, free_alias.args) .map(Unnormalized::skip_norm_wip) .map(|pred| goal.with(cx, pred)), - ); + )?; let actual = match free_alias.kind(cx) { ty::AliasTermKind::FreeTy { def_id } => { - cx.type_of(def_id.into()).instantiate(cx, free_alias.args).skip_norm_wip().into() + let free = + cx.type_of(def_id.into()).instantiate(cx, free_alias.args).skip_norm_wip(); + let free = self.normalize(GoalSource::Misc, goal.param_env, free)?; + free.into() + } + ty::AliasTermKind::FreeConst { def_id } if cx.is_type_const(def_id.into()) => { + let free = cx + .const_of_item(def_id.into()) + .instantiate(cx, free_alias.args) + .skip_norm_wip(); + let free = self.normalize(GoalSource::Misc, goal.param_env, free)?; + + free.into() } - ty::AliasTermKind::FreeConst { def_id } if cx.is_type_const(def_id.into()) => cx - .const_of_item(def_id.into()) - .instantiate(cx, free_alias.args) - .skip_norm_wip() - .into(), ty::AliasTermKind::FreeConst { .. } => { return self.evaluate_const_and_instantiate_normalizes_to_term( goal, diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs index 2f44cc42a5d71..963cf1251a967 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs @@ -52,17 +52,21 @@ where .iter_instantiated(cx, inherent_args) .map(Unnormalized::skip_norm_wip) .map(|pred| goal.with(cx, pred)), - ); + )?; let normalized = match inherent.kind(cx) { ty::AliasTermKind::InherentTy { def_id } => { - cx.type_of(def_id.into()).instantiate(cx, inherent_args).skip_norm_wip().into() + let inherent = + cx.type_of(def_id.into()).instantiate(cx, inherent_args).skip_norm_wip(); + let inherent = self.normalize(GoalSource::Misc, goal.param_env, inherent)?; + inherent.into() + } + ty::AliasTermKind::InherentConst { def_id } if cx.is_type_const(def_id.into()) => { + let inherent = + cx.const_of_item(def_id.into()).instantiate(cx, inherent_args).skip_norm_wip(); + let inherent = self.normalize(GoalSource::Misc, goal.param_env, inherent)?; + inherent.into() } - ty::AliasTermKind::InherentConst { def_id } if cx.is_type_const(def_id.into()) => cx - .const_of_item(def_id.into()) - .instantiate(cx, inherent_args) - .skip_norm_wip() - .into(), ty::AliasTermKind::InherentConst { .. } => { // FIXME(gca): This is dead code at the moment. It should eventually call // self.evaluate_const like projected consts do in consider_impl_candidate in diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index e9a4d7e5919ad..3fdcd9ae8b0c3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -137,8 +137,13 @@ where goal: Goal>, term: ty::AliasTerm, ) { - self.relate_rigid_alias_non_alias(goal.param_env, term, ty::Invariant, goal.predicate.term) - .expect("expected goal term to be fully unconstrained"); + self.relate_rigid_alias_non_alias( + goal.param_env, + term.to_rigid(), + ty::Invariant, + goal.predicate.term, + ) + .expect("expected goal term to be fully unconstrained"); } } @@ -163,6 +168,24 @@ where self.trait_def_id(cx) } + fn fast_reject_param_env( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + assumption: I::Clause, + ) -> Result<(), NoSolution> { + if let Some(projection_pred) = assumption.as_projection_clause() + && projection_pred.item_def_id() == goal.predicate.def_id() + && DeepRejectCtxt::relate_fully_normalized(ecx.cx()).args_may_unify( + goal.predicate.alias.args, + projection_pred.skip_binder().projection_term.args, + ) + { + Ok(()) + } else { + Err(NoSolution) + } + } + fn fast_reject_assumption( ecx: &mut EvalCtxt<'_, D>, goal: Goal, @@ -202,7 +225,7 @@ where .iter_instantiated(cx, goal.predicate.alias.args) .map(Unnormalized::skip_norm_wip) .map(|pred| goal.with(cx, pred)), - ); + )?; then(ecx) } @@ -267,7 +290,7 @@ where .iter_instantiated(cx, impl_args) .map(Unnormalized::skip_norm_wip) .map(|pred| goal.with(cx, pred)); - ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds); + ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds)?; // Bail if the nested goals don't hold here. This is to avoid unnecessarily // computing the `type_of` query for associated types that never apply, as @@ -284,7 +307,7 @@ where .iter_instantiated(cx, goal.predicate.alias.args) .map(Unnormalized::skip_norm_wip) .map(|pred| goal.with(cx, pred)), - ); + )?; let error_response = |ecx: &mut EvalCtxt<'_, D>, guar| { let error_term = match goal.predicate.alias.kind(cx) { @@ -316,7 +339,10 @@ where // This is not the case here and we only prefer adding an ambiguous // nested goal for consistency. ty::TypingMode::Coherence => { - ecx.add_goal(GoalSource::Misc, goal.with(cx, PredicateKind::Ambiguous)); + ecx.add_goal( + GoalSource::Misc, + goal.with(cx, PredicateKind::Ambiguous), + )?; return ecx .evaluate_added_goals_and_make_canonical_response(Certainty::Yes) .map_err(Into::into); @@ -361,7 +387,7 @@ where // would be relevant if any of the nested goals refer to the `term`. // This is not the case here and we only prefer adding an ambiguous // nested goal for consistency. - ecx.add_goal(GoalSource::Misc, goal.with(cx, PredicateKind::Ambiguous)); + ecx.add_goal(GoalSource::Misc, goal.with(cx, PredicateKind::Ambiguous))?; return then(ecx, Certainty::Yes).map_err(Into::into); } else { ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias); @@ -401,23 +427,29 @@ where // Finally we construct the actual value of the associated type. let term = match goal.predicate.alias.kind(cx) { - ty::AliasTermKind::ProjectionTy { .. } => cx - .type_of(target_item_def_id.into()) - .instantiate(cx, target_args) - .skip_norm_wip() - .into(), + ty::AliasTermKind::ProjectionTy { .. } => { + let t = cx + .type_of(target_item_def_id.into()) + .instantiate(cx, target_args) + .skip_norm_wip(); + let t = ecx.normalize(GoalSource::Misc, goal.param_env, t)?; + t.into() + } ty::AliasTermKind::ProjectionConst { .. } if cx.is_type_const(target_item_def_id.into()) => { - cx.const_of_item(target_item_def_id.into()) + let c = cx + .const_of_item(target_item_def_id.into()) .instantiate(cx, target_args) - .skip_norm_wip() - .into() + .skip_norm_wip(); + let c = ecx.normalize(GoalSource::Misc, goal.param_env, c)?; + c.into() } ty::AliasTermKind::ProjectionConst { .. } => { let uv = ty::UnevaluatedConst::new( target_item_def_id.into().try_into().unwrap(), target_args, + ty::IsRigid::No, ); return ecx.evaluate_const_and_instantiate_normalizes_to_term(goal, uv); } @@ -502,6 +534,7 @@ where cx, cx.alias_term_kind_from_def_id(goal.predicate.def_id()), [goal.predicate.self_ty(), inputs], + ty::IsRigid::No, ), term: output.into(), } @@ -559,6 +592,7 @@ where cx, cx.alias_term_kind_from_def_id(goal.predicate.def_id()), [goal.predicate.self_ty(), tupled_inputs_ty], + ty::IsRigid::No, ), output_coroutine_ty.into(), ) @@ -572,6 +606,7 @@ where tupled_inputs_ty.into(), env_region.into(), ], + ty::IsRigid::No, ), output_coroutine_ty.into(), ) @@ -581,6 +616,7 @@ where cx, cx.alias_term_kind_from_def_id(goal.predicate.def_id()), [goal.predicate.self_ty(), tupled_inputs_ty], + ty::IsRigid::No, ), coroutine_return_ty.into(), ) @@ -705,7 +741,7 @@ where cx.require_trait_lang_item(SolverTraitLangItem::Sized), [I::GenericArg::from(goal.predicate.self_ty())], ); - ecx.add_goal(GoalSource::Misc, goal.with(cx, sized_predicate)); + ecx.add_goal(GoalSource::Misc, goal.with(cx, sized_predicate))?; ecx.instantiate_normalizes_to_term(goal, Ty::new_unit(cx).into()); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }); @@ -787,6 +823,7 @@ where ecx.cx(), cx.alias_term_kind_from_def_id(goal.predicate.def_id()), [self_ty], + ty::IsRigid::No, ), term, } @@ -823,6 +860,7 @@ where ecx.cx(), cx.alias_term_kind_from_def_id(goal.predicate.def_id()), [self_ty], + ty::IsRigid::No, ), term, } @@ -913,6 +951,7 @@ where ecx.cx(), cx.alias_term_kind_from_def_id(goal.predicate.def_id()), [self_ty, coroutine.resume_ty()], + ty::IsRigid::No, ), term, } @@ -1047,7 +1086,7 @@ where impl_args: I::GenericArgs, impl_trait_ref: rustc_type_ir::TraitRef, target_container_def_id: I::DefId, - ) -> Result { + ) -> Result { let cx = self.cx(); Ok(if target_container_def_id == impl_trait_ref.def_id.into() { // Default value from the trait definition. No need to rebase. @@ -1072,7 +1111,7 @@ where .iter_instantiated(cx, target_args) .map(Unnormalized::skip_norm_wip) .map(|pred| goal.with(cx, pred)), - ); + )?; goal.predicate.alias.args.rebase_onto(cx, impl_trait_ref.def_id.into(), target_args) }) } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs index 57d10b4ac1fe1..ce5bd57c64677 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs @@ -32,12 +32,12 @@ where opaque_ty.args, goal.param_env, expected, - ); + )?; // Trying to normalize an opaque type during coherence is always ambiguous. // We add a nested ambiguous goal here instead of using `Certainty::AMBIGUOUS`. // This allows us to return the nested goals to the parent `AliasRelate` goal. // This can then allow nested goals to fail after we've constrained the `term`. - self.add_goal(GoalSource::Misc, goal.with(cx, ty::PredicateKind::Ambiguous)); + self.add_goal(GoalSource::Misc, goal.with(cx, ty::PredicateKind::Ambiguous))?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) .map_err(Into::into) } @@ -92,6 +92,8 @@ where .type_of_opaque_hir_typeck(def_id) .instantiate(cx, opaque_ty.args) .skip_norm_wip(); + let actual = + self.normalize(GoalSource::Misc, goal.param_env, actual)?; let actual = fold_regions(cx, actual, |re, _dbi| match re.kind() { ty::ReErased => self.next_region_var(), _ => re, @@ -109,7 +111,7 @@ where normalized_args, goal.param_env, expected, - ); + )?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) .map_err(Into::into) } @@ -127,6 +129,7 @@ where let actual = cx.type_of(def_id.into()).instantiate(cx, opaque_ty.args).skip_norm_wip(); + let actual = self.normalize(GoalSource::Misc, goal.param_env, actual)?; // FIXME: Actually use a proper binder here instead of relying on `ReErased`. // // This is also probably unsound or sth :shrug: @@ -142,6 +145,7 @@ where // FIXME: Add an assertion that opaque type storage is empty. let actual = cx.type_of(def_id.into()).instantiate(cx, opaque_ty.args).skip_norm_wip(); + let actual = self.normalize(GoalSource::Misc, goal.param_env, actual)?; self.eq(goal.param_env, expected, actual)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) .map_err(Into::into) diff --git a/compiler/rustc_next_trait_solver/src/solve/project_goals.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals.rs index af6d0aad25597..7a70e7d29005c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/project_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals.rs @@ -26,7 +26,7 @@ where ), ); // A projection goal holds if the alias is equal to the expected term. - self.add_goal(GoalSource::TypeRelating, goal); + self.add_goal(GoalSource::TypeRelating, goal)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index f3ace5a70c69c..cf02e8800130d 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -106,7 +106,7 @@ where .iter_instantiated(cx, impl_args) .map(Unnormalized::skip_norm_wip) .map(|pred| goal.with(cx, pred)); - ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds); + ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds)?; // We currently elaborate all supertrait outlives obligations from impls. // This can be removed when we actually do coinduction correctly, and prove @@ -117,7 +117,7 @@ where .iter_instantiated(cx, impl_args) .map(Unnormalized::skip_norm_wip) .map(|pred| goal.with(cx, pred)), - ); + )?; then(ecx, maximal_certainty).map_err(Into::into) }) @@ -131,6 +131,46 @@ where .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } + fn fast_reject_param_env( + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + assumption: I::Clause, + ) -> Result<(), NoSolution> { + fn trait_def_id_matches( + cx: I, + clause_def_id: I::TraitId, + goal_def_id: I::TraitId, + polarity: PredicatePolarity, + ) -> bool { + clause_def_id == goal_def_id + // PERF(sized-hierarchy): Sizedness supertraits aren't elaborated to improve perf, so + // check for a `MetaSized` supertrait being matched against a `Sized` assumption. + // + // `PointeeSized` bounds are syntactic sugar for a lack of bounds so don't need this. + || (polarity == PredicatePolarity::Positive + && cx.is_trait_lang_item(clause_def_id, SolverTraitLangItem::Sized) + && cx.is_trait_lang_item(goal_def_id, SolverTraitLangItem::MetaSized)) + } + + if let Some(trait_clause) = assumption.as_trait_clause() + && trait_clause.polarity() == goal.predicate.polarity + && trait_def_id_matches( + ecx.cx(), + trait_clause.def_id(), + goal.predicate.def_id(), + goal.predicate.polarity, + ) + && DeepRejectCtxt::relate_fully_normalized(ecx.cx()).args_may_unify( + goal.predicate.trait_ref.args, + trait_clause.skip_binder().trait_ref.args, + ) + { + return Ok(()); + } else { + Err(NoSolution) + } + } + fn fast_reject_assumption( ecx: &mut EvalCtxt<'_, D>, goal: Goal, @@ -286,7 +326,7 @@ where // `GoalSource::ImplWhereClause` here would be incorrect, as we also // impl them, which means we're "stepping out of the impl constructor" // again. To handle this, we treat these cycles as ambiguous for now. - ecx.add_goals(GoalSource::Misc, nested_obligations); + ecx.add_goals(GoalSource::Misc, nested_obligations)?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -736,13 +776,13 @@ where tys.iter().map(|elem_ty| { goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty])) }), - ); + )?; } ty::Array(elem_ty, _) => { ecx.add_goal( GoalSource::ImplWhereBound, goal.with(cx, ty::TraitRef::new(cx, goal.predicate.def_id(), [elem_ty])), - ); + )?; } // All other types implement `BikeshedGuaranteedNoDrop` only if @@ -783,7 +823,7 @@ where [ty], ), ), - ); + )?; } ty::Bound(..) @@ -865,6 +905,8 @@ where } } + // FIXME(field_projections): This function does some questionable incomplete stuff by + // returning `Err(NoSolution)` on ambiguity. fn consider_builtin_field_candidate( ecx: &mut EvalCtxt<'_, D>, goal: Goal, @@ -890,14 +932,14 @@ where param_env: goal.param_env, predicate: TraitRef::new(ecx.cx(), sized_trait, [base]).upcast(ecx.cx()), }, - ); + )?; ecx.add_goal( GoalSource::ImplWhereBound, Goal { param_env: goal.param_env, predicate: TraitRef::new(ecx.cx(), sized_trait, [ty]).upcast(ecx.cx()), }, - ); + )?; ecx.try_evaluate_added_goals()? == Certainty::Yes } && match base.kind() { @@ -1015,7 +1057,7 @@ where ecx.add_goals( GoalSource::ImplWhereBound, b_data.iter().map(|pred| goal.with(cx, pred.with_self_ty(cx, a_ty))), - ); + )?; // The type must be `Sized` to be unsized. ecx.add_goal( @@ -1028,10 +1070,10 @@ where [a_ty], ), ), - ); + )?; // The type must outlive the lifetime of the `dyn` we're unsizing into. - ecx.add_goal(GoalSource::Misc, goal.with(cx, ty::OutlivesPredicate(a_ty, b_region))); + ecx.add_goal(GoalSource::Misc, goal.with(cx, ty::OutlivesPredicate(a_ty, b_region)))?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -1151,7 +1193,7 @@ where ecx.add_goal( GoalSource::ImplWhereBound, Goal::new(ecx.cx(), param_env, ty::OutlivesPredicate(a_region, b_region)), - ); + )?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes).map_err(Into::into) }) @@ -1232,7 +1274,7 @@ where [a_tail_ty, b_tail_ty], ), ), - ); + )?; self.probe_builtin_trait_candidate(BuiltinImplSource::Misc) .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } @@ -1372,7 +1414,7 @@ where .collect::>() }, ); - ecx.add_goals(GoalSource::ImplWhereBound, goals); + ecx.add_goals(GoalSource::ImplWhereBound, goals)?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } diff --git a/compiler/rustc_public_bridge/src/builder.rs b/compiler/rustc_public_bridge/src/builder.rs index ea7f37d72d0dd..525582fc835f3 100644 --- a/compiler/rustc_public_bridge/src/builder.rs +++ b/compiler/rustc_public_bridge/src/builder.rs @@ -38,7 +38,7 @@ impl<'tcx> BodyBuilder<'tcx> { let mut mono_body = self.instance.instantiate_mir_and_normalize_erasing_regions( self.tcx, ty::TypingEnv::fully_monomorphized(), - ty::EarlyBinder::bind(body), + ty::EarlyBinder::bind(self.tcx, body), ); self.visit_body(&mut mono_body); mono_body diff --git a/compiler/rustc_query_impl/src/handle_cycle_error.rs b/compiler/rustc_query_impl/src/handle_cycle_error.rs index 79e7788cafe81..d4156ade79bd7 100644 --- a/compiler/rustc_query_impl/src/handle_cycle_error.rs +++ b/compiler/rustc_query_impl/src/handle_cycle_error.rs @@ -43,9 +43,10 @@ pub(crate) fn fn_sig<'tcx>( unreachable!() }; - ty::EarlyBinder::bind(ty::Binder::dummy( - tcx.mk_fn_sig_safe_rust_abi(std::iter::repeat_n(err, arity), err), - )) + ty::EarlyBinder::bind( + tcx, + ty::Binder::dummy(tcx.mk_fn_sig_safe_rust_abi(std::iter::repeat_n(err, arity), err)), + ) } pub(crate) fn check_representability<'tcx>( diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index 0810e327b63e3..a80ffccbfdbbf 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -249,6 +249,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc tcx, assoc_item.def_id, super_trait_ref.args, + ty::IsRigid::No, ); let term = tcx.normalize_erasing_regions( ty::TypingEnv::fully_monomorphized(), @@ -506,7 +507,7 @@ fn implemented_method<'tcx>( trait_method = assoc; method_id = trait_method_def_id; trait_id = tcx.parent(method_id); - trait_ref = ty::EarlyBinder::bind(TraitRef::from_assoc(tcx, trait_id, instance.args)); + trait_ref = ty::EarlyBinder::bind(tcx, TraitRef::from_assoc(tcx, trait_id, instance.args)); trait_id } else { return None; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 51a4186658c62..a963b76261247 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -2123,7 +2123,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let impl_trait_ref = ocx.normalize( &ObligationCause::dummy(), param_env, - ty::EarlyBinder::bind(single.trait_ref).instantiate(self.tcx, impl_args), + ty::EarlyBinder::bind(self.tcx, single.trait_ref) + .instantiate(self.tcx, impl_args), ); ocx.register_obligations( @@ -2792,6 +2793,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } self.probe(|_| { + let pred = ty::reset_rigid_aliases(self.tcx, pred); let cleaned_pred = pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() }); diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 26139926dae41..3a8186352c1d1 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -5360,7 +5360,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // This corresponds to `::Item = _`. let projection = ty::Binder::dummy(ty::PredicateKind::Clause( ty::ClauseKind::Projection(ty::ProjectionPredicate { - projection_term: ty::AliasTerm::new_from_args(self.tcx, kind.into(), args), + projection_term: ty::AliasTerm::new_from_args( + self.tcx, + kind.into(), + args, + ty::IsRigid::No, + ), term: ty.into(), }), )); diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index ed345d98b5392..6f4bb4e1f1f0e 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -6,7 +6,7 @@ use rustc_infer::traits::query::NoSolution; use rustc_infer::traits::{ FromSolverError, PredicateObligation, PredicateObligations, TraitEngine, }; -use rustc_middle::ty::{TyCtxt, TypeVisitableExt, TypingMode}; +use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, TypingMode}; use rustc_next_trait_solver::delegate::SolverDelegate as _; use rustc_next_trait_solver::solve::{ GoalEvaluation, GoalStalledOn, HasChanged, MaybeInfo, SolverDelegateEvalExt as _, @@ -18,7 +18,7 @@ use tracing::instrument; use self::derive_errors::*; use super::Certainty; use super::delegate::SolverDelegate; -use crate::traits::{FulfillmentError, ScrubbedTraitError}; +use crate::traits::{FulfillmentError, ObligationCtxt, ScrubbedTraitError}; mod derive_errors; @@ -151,9 +151,16 @@ where fn register_predicate_obligation( &mut self, infcx: &InferCtxt<'tcx>, - obligation: PredicateObligation<'tcx>, + mut obligation: PredicateObligation<'tcx>, ) { assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots()); + let ocx = ObligationCtxt::new(infcx); + obligation.predicate = ocx.normalize( + &obligation.cause, + obligation.param_env, + ty::Unnormalized::new_wip(obligation.predicate), + ); + self.register_predicate_obligations(infcx, ocx.into_pending_obligations()); self.obligations.register(obligation, None); } diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 7c21dc161a1ec..f3c72be0e457b 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -6,11 +6,11 @@ use rustc_infer::traits::{ }; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{ - self, Binder, Flags, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, - UniverseIndex, Unnormalized, + self, AliasTerm, Binder, Flags, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeVisitableExt, UniverseIndex, Unnormalized, }; -use rustc_next_trait_solver::normalize::NormalizationFolder; -use rustc_next_trait_solver::solve::SolverDelegateEvalExt; +use rustc_next_trait_solver::normalize::{NormalizationFolder, NormalizationWasAmbiguous}; +use rustc_next_trait_solver::solve::{NoSolution, SolverDelegateEvalExt}; use super::{FulfillmentCtxt, NextSolverError}; use crate::solve::{Certainty, SolverDelegate}; @@ -42,38 +42,54 @@ where let infcx = at.infcx; let value = value.skip_normalization(); let value = infcx.resolve_vars_if_possible(value); + + // TODO: detect all typing env change. + // if !value.has_non_rigid_aliases() { + // return Normalized { value, obligations: Default::default() }; + // } + let original_value = value.clone(); - let mut folder = - NormalizationFolder::new(infcx, universes.clone(), Default::default(), |alias_term| { - let delegate = <&SolverDelegate<'tcx>>::from(infcx); - let infer_term = delegate.next_term_var_of_kind(alias_term, at.cause.span); - let predicate = ty::PredicateKind::AliasRelate( - alias_term.into(), - infer_term.into(), - ty::AliasRelationDirection::Equate, - ); - let goal = Goal::new(infcx.tcx, at.param_env, predicate); - let result = delegate.evaluate_root_goal(goal, at.cause.span, None)?; - let normalized = infcx.resolve_vars_if_possible(infer_term); - let stalled_goal = match result.certainty { - Certainty::Yes => None, - Certainty::Maybe { .. } => Some(infcx.resolve_vars_if_possible(result.goal)), - }; - Ok((normalized, stalled_goal)) - }); - if let Ok(value) = value.try_fold_with(&mut folder) { - let obligations = folder - .stalled_goals() - .into_iter() - .map(|goal| { - Obligation::new(infcx.tcx, at.cause.clone(), goal.param_env, goal.predicate) - }) - .collect(); - Normalized { value, obligations } - } else { - let mut replacer = ReplaceAliasWithInfer { at, obligations: Default::default(), universes }; - let value = original_value.fold_with(&mut replacer); - Normalized { value, obligations: replacer.obligations } + let mut stalled_goals = vec![]; + let mut folder = NormalizationFolder::new(infcx, universes.clone(), |alias_term| { + let delegate = <&SolverDelegate<'tcx>>::from(infcx); + let infer_term = delegate.next_term_var_for_alias(alias_term, at.cause.span); + let predicate = ty::PredicateKind::AliasRelate( + alias_term.to_term(infcx.tcx), + infer_term.into(), + ty::AliasRelationDirection::Equate, + ); + let goal = Goal::new(infcx.tcx, at.param_env, predicate); + let result = match delegate.evaluate_root_goal(goal, at.cause.span, None) { + Ok(result) => result, + Err(err) => return Err(err), + }; + let normalized = infcx.resolve_vars_if_possible(infer_term); + let normalization_was_ambiguous = match result.certainty { + Certainty::Yes => NormalizationWasAmbiguous::No, + Certainty::Maybe { .. } => { + stalled_goals.push(infcx.resolve_vars_if_possible(goal)); + NormalizationWasAmbiguous::Yes + } + }; + Ok((normalized, normalization_was_ambiguous)) + }); + + match value.try_fold_with(&mut folder) { + Ok(value) => { + let obligations = stalled_goals + .into_iter() + .map(|goal| { + Obligation::new(infcx.tcx, at.cause.clone(), goal.param_env, goal.predicate) + }) + .collect(); + Normalized { value, obligations } + } + Err(NoSolution) => { + let mut replacer = + ReplaceAliasWithInfer { at, obligations: Default::default(), universes }; + let value = original_value.fold_with(&mut replacer); + Normalized { value, obligations: replacer.obligations } + } } } @@ -84,15 +100,15 @@ struct ReplaceAliasWithInfer<'me, 'tcx> { } impl<'me, 'tcx> ReplaceAliasWithInfer<'me, 'tcx> { - fn term_to_infer(&mut self, alias_term: ty::Term<'tcx>) -> ty::Term<'tcx> { + fn alias_term_to_infer(&mut self, alias_term: ty::AliasTerm<'tcx>) -> ty::Term<'tcx> { let infcx = self.at.infcx; - let infer_term = infcx.next_term_var_of_kind(alias_term, self.at.cause.span); + let infer_term = infcx.next_term_var_for_alias(alias_term, self.at.cause.span); let obligation = Obligation::new( infcx.tcx, self.at.cause.clone(), self.at.param_env, ty::PredicateKind::AliasRelate( - alias_term.into(), + alias_term.to_term(infcx.tcx), infer_term.into(), ty::AliasRelationDirection::Equate, ), @@ -123,15 +139,14 @@ impl<'me, 'tcx> TypeFolder> for ReplaceAliasWithInfer<'me, 'tcx> { } let ty = ty.super_fold_with(self); - let ty::Alias(..) = *ty.kind() else { return ty }; - - if ty.has_escaping_bound_vars() { + let ty::Alias(alias_ty) = *ty.kind() else { return ty }; + if alias_ty.has_escaping_bound_vars() { let (replaced, ..) = - BoundVarReplacer::replace_bound_vars(self.at.infcx, &mut self.universes, ty); - let _ = self.term_to_infer(replaced.into()); + BoundVarReplacer::replace_bound_vars(self.at.infcx, &mut self.universes, alias_ty); + let _ = self.alias_term_to_infer(replaced.into()); ty } else { - self.term_to_infer(ty.into()).expect_type() + self.alias_term_to_infer(alias_ty.into()).expect_type() } } @@ -141,17 +156,23 @@ impl<'me, 'tcx> TypeFolder> for ReplaceAliasWithInfer<'me, 'tcx> { } let ct = ct.super_fold_with(self); - let ty::ConstKind::Unevaluated(..) = ct.kind() else { return ct }; + let ty::ConstKind::Unevaluated(uv) = ct.kind() else { return ct }; if ct.has_escaping_bound_vars() { let (replaced, ..) = - BoundVarReplacer::replace_bound_vars(self.at.infcx, &mut self.universes, ct); - let _ = self.term_to_infer(replaced.into()); + BoundVarReplacer::replace_bound_vars(self.at.infcx, &mut self.universes, uv); + let _ = + self.alias_term_to_infer(AliasTerm::from_unevaluated_const(self.cx(), replaced)); ct } else { - self.term_to_infer(ct.into()).expect_const() + self.alias_term_to_infer(AliasTerm::from_unevaluated_const(self.cx(), uv)) + .expect_const() } } + + fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { + if p.allow_normalization() { p.super_fold_with(self) } else { p } + } } /// Deeply normalize all aliases in `value`. This does not handle inference and expects @@ -285,4 +306,8 @@ impl<'tcx> TypeFolder> for DeeplyNormalizeForDiagnosticsFolder<'_, Err(_) => ct.super_fold_with(self), } } + + fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { + if p.allow_normalization() { p.super_fold_with(self) } else { p } + } } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 49cc2833cd978..796b6f04abbf7 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -537,7 +537,7 @@ fn impl_intersection_has_negative_obligation( // So there are no infer variables left now, except regions which aren't resolved by `resolve_vars_if_possible`. assert!(!impl1_header_args.has_non_region_infer()); - let param_env = ty::EarlyBinder::bind(tcx.param_env(impl1_def_id)) + let param_env = ty::EarlyBinder::bind(tcx, tcx.param_env(impl1_def_id)) .instantiate(tcx, impl1_header_args) .skip_norm_wip(); diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index a018a150a7067..1739d914ed8c4 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -605,7 +605,7 @@ fn receiver_for_self_ty<'tcx>( if param.index == 0 { self_ty.into() } else { tcx.mk_param_from_def(param) } }); - let result = EarlyBinder::bind(receiver_ty).instantiate(tcx, args).skip_norm_wip(); + let result = EarlyBinder::bind(tcx, receiver_ty).instantiate(tcx, args).skip_norm_wip(); debug!( "receiver_for_self_ty({:?}, {:?}, {:?}) = {:?}", receiver_ty, self_ty, method_def_id, result diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index a834dbd1604f8..ec3417796f85e 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -258,12 +258,6 @@ fn do_normalize_predicates<'tcx>( elaborated_env: ty::ParamEnv<'tcx>, predicates: Vec>, ) -> Result>, ErrorGuaranteed> { - // Even if we move back to eager normalization elsewhere, - // param env normalization remains lazy in the next solver. - if tcx.next_trait_solver_globally() { - return Ok(predicates); - } - // FIXME. We should really... do something with these region // obligations. But this call just continues the older // behavior (i.e., doesn't cause any new bugs), and it would @@ -281,6 +275,8 @@ fn do_normalize_predicates<'tcx>( let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new_with_diagnostics(&infcx); let predicates = ocx.normalize(&cause, elaborated_env, Unnormalized::new_wip(predicates)); + // FIXME: typing mode change causes rigid opaque in non body analysis invalid. + let predicates = ty::reset_rigid_aliases(tcx, predicates); let errors = ocx.evaluate_obligations_error_on_ambiguity(); if !errors.is_empty() { @@ -426,7 +422,7 @@ pub fn normalize_param_env_or_error<'tcx>( // a circularity. // // The way we handle this is by normalizing the param-env inside an unnormalized version - // of the param-env, which means that if the param-env contains unnormalized projections, + // of the param-env, which mefn normalize_param_envans that if the param-env contains unnormalized projections, // we'll have some normalization failures. This is unfortunate. // // Lazy normalization would basically handle this by treating just the @@ -716,7 +712,7 @@ pub fn try_evaluate_const<'tcx>( } }; - let uv = ty::UnevaluatedConst::new(uv.def, args); + let uv = ty::UnevaluatedConst::new(uv.def, args, ty::IsRigid::No); let erased_uv = tcx.erase_and_anonymize_regions(uv); use rustc_middle::mir::interpret::ErrorHandled; @@ -924,7 +920,9 @@ fn is_impossible_associated_item( tcx, ObligationCause::dummy_with_span(*span), param_env, - ty::EarlyBinder::bind(*pred).instantiate(tcx, impl_trait_ref.args).skip_norm_wip(), + ty::EarlyBinder::bind(tcx, *pred) + .instantiate(tcx, impl_trait_ref.args) + .skip_norm_wip(), ) }) }); diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 900d55cc556fc..c0f4b6b68fbd9 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1559,6 +1559,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( tcx, ty::AliasTermKind::ProjectionTy { def_id: item_def_id }, args, + ty::IsRigid::No, ), term, }; @@ -1696,6 +1697,7 @@ fn confirm_callable_candidate<'cx, 'tcx>( tcx, ty::AliasTermKind::ProjectionTy { def_id: fn_once_output_def_id }, trait_ref.args, + ty::IsRigid::No, ), term: ret_type.into(), }); @@ -1783,11 +1785,13 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( tcx, obligation.predicate.kind, [self_ty, sig.tupled_inputs_ty], + ty::IsRigid::No, ), sym::CallRefFuture => ty::AliasTerm::new( tcx, obligation.predicate.kind, [ty::GenericArg::from(self_ty), sig.tupled_inputs_ty.into(), env_region.into()], + ty::IsRigid::No, ), name => bug!("no such associated type: {name}"), }; @@ -1813,6 +1817,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( tcx, obligation.predicate.kind, [self_ty, Ty::new_tup(tcx, sig.inputs())], + ty::IsRigid::No, ), sym::CallRefFuture => ty::AliasTerm::new( tcx, @@ -1822,6 +1827,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( Ty::new_tup(tcx, sig.inputs()).into(), env_region.into(), ], + ty::IsRigid::No, ), name => bug!("no such associated type: {name}"), }; @@ -1843,13 +1849,17 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( name => bug!("no such associated type: {name}"), }; let projection_term = match item_name { - sym::CallOnceFuture | sym::Output => { - ty::AliasTerm::new(tcx, obligation.predicate.kind, [self_ty, sig.inputs()[0]]) - } + sym::CallOnceFuture | sym::Output => ty::AliasTerm::new( + tcx, + obligation.predicate.kind, + [self_ty, sig.inputs()[0]], + ty::IsRigid::No, + ), sym::CallRefFuture => ty::AliasTerm::new( tcx, obligation.predicate.kind, [ty::GenericArg::from(self_ty), sig.inputs()[0].into(), env_region.into()], + ty::IsRigid::No, ), name => bug!("no such associated type: {name}"), }; diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index 6a6ade3b23b36..a9ed6126ea752 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -391,17 +391,17 @@ pub fn dtorck_constraint_for_ty_inner<'tcx>( constraints.dtorck_types.extend( dtorck_types .iter() - .map(|t| EarlyBinder::bind(*t).instantiate(tcx, args).skip_norm_wip()), + .map(|t| EarlyBinder::bind(tcx, *t).instantiate(tcx, args).skip_norm_wip()), ); constraints.outlives.extend( outlives .iter() - .map(|t| EarlyBinder::bind(*t).instantiate(tcx, args).skip_norm_wip()), + .map(|t| EarlyBinder::bind(tcx, *t).instantiate(tcx, args).skip_norm_wip()), ); constraints.overflows.extend( overflows .iter() - .map(|t| EarlyBinder::bind(*t).instantiate(tcx, args).skip_norm_wip()), + .map(|t| EarlyBinder::bind(tcx, *t).instantiate(tcx, args).skip_norm_wip()), ); } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index e8c5d10c78ce3..bb30f0ca8a962 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -257,7 +257,12 @@ impl<'a, 'tcx> FallibleTypeFolder> for QueryNormalizer<'a, 'tcx> { } kind @ (ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }) => self - .try_fold_free_or_assoc(ty::AliasTerm::new(self.cx(), kind.into(), data.args))? + .try_fold_free_or_assoc(ty::AliasTerm::new( + self.cx(), + kind.into(), + data.args, + ty::IsRigid::No, + ))? .expect_type(), }; diff --git a/compiler/rustc_traits/src/coroutine_witnesses.rs b/compiler/rustc_traits/src/coroutine_witnesses.rs index 83a77f17b28ce..4e3dcfddfb5ab 100644 --- a/compiler/rustc_traits/src/coroutine_witnesses.rs +++ b/compiler/rustc_traits/src/coroutine_witnesses.rs @@ -37,10 +37,13 @@ pub(crate) fn coroutine_hidden_types<'tcx>( let assumptions = compute_assumptions(tcx, def_id, bound_tys); - ty::EarlyBinder::bind(ty::Binder::bind_with_vars( - ty::CoroutineWitnessTypes { types: bound_tys, assumptions }, - tcx.mk_bound_variable_kinds(&vars), - )) + ty::EarlyBinder::bind( + tcx, + ty::Binder::bind_with_vars( + ty::CoroutineWitnessTypes { types: bound_tys, assumptions }, + tcx.mk_bound_variable_kinds(&vars), + ), + ) } fn compute_assumptions<'tcx>( diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 24415c5a50e97..47eccc76b94d3 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -70,7 +70,7 @@ fn recurse_build<'tcx>( } &ExprKind::ZstLiteral { user_ty: _ } => ty::Const::zero_sized(tcx, node.ty), &ExprKind::NamedConst { def_id, args, user_ty: _ } => { - let uneval = ty::UnevaluatedConst::new(def_id, args); + let uneval = ty::UnevaluatedConst::new(def_id, args, ty::IsRigid::No); ty::Const::new_unevaluated(tcx, uneval) } ExprKind::ConstParam { param, .. } => ty::Const::new_param(tcx, *param), @@ -381,7 +381,7 @@ fn thir_abstract_const<'tcx>( let root_span = body.exprs[body_id].span; - Ok(Some(ty::EarlyBinder::bind(recurse_build(tcx, body, body_id, root_span)?))) + Ok(Some(ty::EarlyBinder::bind(tcx, recurse_build(tcx, body, body_id, root_span)?))) } pub(crate) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 659229a58d539..2acbb90961ecb 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -116,10 +116,12 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' tcx.impl_trait_ref(impl_def_id).instantiate_identity().skip_norm_wip().args, ); tcx.arena.alloc_from_iter( - ty::EarlyBinder::bind(tcx.assumed_wf_types_for_rpitit(rpitit_def_id)) - .iter_instantiated_copied(tcx, args) - .map(Unnormalized::skip_norm_wip) - .chain(tcx.assumed_wf_types(impl_def_id).into_iter().copied()), + ty::EarlyBinder::bind_no_rigid_aliases( + tcx.assumed_wf_types_for_rpitit(rpitit_def_id), + ) + .iter_instantiated_copied(tcx, args) + .map(Unnormalized::skip_norm_wip) + .chain(tcx.assumed_wf_types(impl_def_id).into_iter().copied()), ) } } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 9cc15a374ff70..307a3e46c1f09 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -52,7 +52,10 @@ fn layout_of<'tcx>( // One that can be called after typecheck has completed and can use // `normalize_erasing_regions` here and another one that can be called // before typecheck has completed and uses `try_normalize_erasing_regions`. - let ty = match tcx.try_normalize_erasing_regions(typing_env, Unnormalized::new_wip(ty)) { + let ty = match tcx.try_normalize_erasing_regions( + typing_env, + Unnormalized::new_wip(ty::reset_rigid_aliases(tcx, ty)), + ) { Ok(t) => t, Err(normalization_error) => { return Err(tcx @@ -527,7 +530,7 @@ fn layout_of_uncached<'tcx>( .field_tys .iter() .map(|local| { - let field_ty = EarlyBinder::bind(local.ty); + let field_ty = EarlyBinder::bind(tcx, local.ty); let uninit_ty = Ty::new_maybe_uninit(tcx, field_ty.instantiate(tcx, args).skip_norm_wip()); cx.spanned_layout_of(uninit_ty, local.source_info.span) diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 89c526bf8d70a..72191ba32716c 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -211,7 +211,7 @@ where for field_ty in &witness.field_tys { queue_type( self, - EarlyBinder::bind(field_ty.ty) + EarlyBinder::bind(tcx, field_ty.ty) .instantiate(tcx, args) .skip_norm_wip(), ); @@ -340,7 +340,9 @@ fn drop_tys_helper<'tcx>( match subty.kind() { ty::Adt(adt_id, args) => { for subty in tcx.adt_drop_tys(adt_id.did())? { - vec.push(EarlyBinder::bind(subty).instantiate(tcx, args).skip_norm_wip()); + vec.push( + EarlyBinder::bind(tcx, subty).instantiate(tcx, args).skip_norm_wip(), + ); } } _ => vec.push(subty), diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 1459fb5077e65..ddf093b7743e3 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -144,7 +144,7 @@ fn adt_sizedness_constraint<'tcx>( return None; } - Some(ty::EarlyBinder::bind(constraint_ty)) + Some(ty::EarlyBinder::bind(tcx, constraint_ty)) } /// See `ParamEnv` struct definition for details. diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index de3e04626f823..5e1c8f20f01ea 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -387,8 +387,15 @@ generate!( impl !TypeVisitable for ty::EarlyBinder {} ); +impl> EarlyBinder { + pub fn bind(cx: I, value: T) -> EarlyBinder { + let value = ty::reset_rigid_aliases(cx, value); + EarlyBinder { value, _tcx: PhantomData } + } +} + impl EarlyBinder { - pub fn bind(value: T) -> EarlyBinder { + pub fn bind_no_rigid_aliases(value: T) -> EarlyBinder { EarlyBinder { value, _tcx: PhantomData } } @@ -647,6 +654,8 @@ impl> ty::EarlyBinder { where A: SliceLike, { + debug_assert!(!self.value.has_rigid_aliases()); + // Nothing to fold, so let's avoid visiting things and possibly re-hashing/equating // them when interning. Perf testing found this to be a modest improvement. // See: @@ -671,6 +680,8 @@ impl> ty::EarlyBinder { /// - Inside of the body of `foo`, we treat `T` as a placeholder by calling /// `instantiate_identity` to discharge the `EarlyBinder`. pub fn instantiate_identity(self) -> Unnormalized { + debug_assert!(!self.value.has_rigid_aliases()); + // FIXME(#155345): In case the bound value was already normalized, this // is unnecessary. We may want to track explicitly whether `EarlyBinder` // contains something that has been normalized already. diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 4017aab7a6b57..1d85e78b8792a 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -77,14 +77,19 @@ impl fmt::Debug for ConstKind { pub struct UnevaluatedConst { pub def: I::UnevaluatedConstId, pub args: I::GenericArgs, + pub is_rigid: ty::IsRigid, } impl Eq for UnevaluatedConst {} impl UnevaluatedConst { #[inline] - pub fn new(def: I::UnevaluatedConstId, args: I::GenericArgs) -> UnevaluatedConst { - UnevaluatedConst { def, args } + pub fn new( + def: I::UnevaluatedConstId, + args: I::GenericArgs, + is_rigid: ty::IsRigid, + ) -> UnevaluatedConst { + UnevaluatedConst { def, args, is_rigid } } } diff --git a/compiler/rustc_type_ir/src/error.rs b/compiler/rustc_type_ir/src/error.rs index 15fbd985d9630..6af014fbfb874 100644 --- a/compiler/rustc_type_ir/src/error.rs +++ b/compiler/rustc_type_ir/src/error.rs @@ -2,7 +2,7 @@ use derive_where::derive_where; use rustc_abi::ExternAbi; use rustc_type_ir_macros::{GenericTypeVisitable, TypeFoldable_Generic, TypeVisitable_Generic}; -use crate::solve::NoSolution; +use crate::solve::{NoSolution, NoSolutionOrRerunNonErased}; use crate::{self as ty, Interner}; #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -100,3 +100,9 @@ impl From> for NoSolution { NoSolution } } + +impl From> for NoSolutionOrRerunNonErased { + fn from(_: TypeError) -> NoSolutionOrRerunNonErased { + NoSolutionOrRerunNonErased::NoSolution(NoSolution) + } +} diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs index 26d98b5d8ad7d..43734d6fcfa5f 100644 --- a/compiler/rustc_type_ir/src/fast_reject.rs +++ b/compiler/rustc_type_ir/src/fast_reject.rs @@ -161,6 +161,10 @@ impl SimplifiedType { } } +const HANDLE_AS_INFER: u8 = 0; +const HANDLE_UNNORMALIZED: u8 = 1; +const HANDLE_FULLY_NORMALIZED: u8 = 2; + /// Given generic arguments, could they be unified after /// replacing parameters with inference variables or placeholders. /// This behavior is toggled using the const generics. @@ -172,37 +176,45 @@ impl SimplifiedType { /// impls only have to overlap for some value, so we treat parameters /// on both sides like inference variables. #[derive(Debug, Clone, Copy)] -pub struct DeepRejectCtxt< - I: Interner, - const INSTANTIATE_LHS_WITH_INFER: bool, - const INSTANTIATE_RHS_WITH_INFER: bool, -> { +pub struct DeepRejectCtxt { _interner: PhantomData, } -impl DeepRejectCtxt { +impl DeepRejectCtxt { /// Treat parameters in both the lhs and the rhs as rigid. - pub fn relate_rigid_rigid(_interner: I) -> DeepRejectCtxt { + pub fn relate_rigid_rigid( + _interner: I, + ) -> DeepRejectCtxt { DeepRejectCtxt { _interner: PhantomData } } } -impl DeepRejectCtxt { +impl DeepRejectCtxt { /// Treat parameters in both the lhs and the rhs as infer vars. - pub fn relate_infer_infer(_interner: I) -> DeepRejectCtxt { + pub fn relate_infer_infer(_interner: I) -> DeepRejectCtxt { DeepRejectCtxt { _interner: PhantomData } } } -impl DeepRejectCtxt { +impl DeepRejectCtxt { /// Treat parameters in the lhs as rigid, and in rhs as infer vars. - pub fn relate_rigid_infer(_interner: I) -> DeepRejectCtxt { + pub fn relate_rigid_infer( + _interner: I, + ) -> DeepRejectCtxt { + DeepRejectCtxt { _interner: PhantomData } + } +} + +impl DeepRejectCtxt { + pub fn relate_fully_normalized( + _interner: I, + ) -> DeepRejectCtxt { DeepRejectCtxt { _interner: PhantomData } } } -impl - DeepRejectCtxt +impl + DeepRejectCtxt { // Quite arbitrary. Large enough to only affect a very tiny amount of impls/crates // and small enough to prevent hangs. @@ -257,11 +269,16 @@ impl { - if INSTANTIATE_RHS_WITH_INFER { + if HANDLE_RHS < HANDLE_UNNORMALIZED { + return true; + } + } + ty::Alias(_) => { + if HANDLE_RHS < HANDLE_FULLY_NORMALIZED { return true; } } - ty::Error(_) | ty::Alias(..) | ty::Bound(..) => return true, + ty::Error(_) | ty::Bound(..) => return true, ty::Infer(var) => return self.var_and_ty_may_unify(var, lhs), // These types only unify with inference variables or their own @@ -324,7 +341,7 @@ impl { - INSTANTIATE_LHS_WITH_INFER + HANDLE_LHS < HANDLE_UNNORMALIZED || match rhs.kind() { ty::Param(rhs) => lhs == rhs, _ => false, @@ -343,7 +360,15 @@ impl true, + ty::Alias(lhs) => { + HANDLE_LHS < HANDLE_FULLY_NORMALIZED + || match rhs.kind() { + ty::Alias(rhs) => { + lhs.kind == rhs.kind && self.args_may_unify(lhs.args, rhs.args) + } + _ => false, + } + } ty::Int(_) | ty::Uint(_) @@ -462,7 +487,7 @@ impl bool { match rhs.kind() { ty::ConstKind::Param(_) => { - if INSTANTIATE_RHS_WITH_INFER { + if HANDLE_RHS < HANDLE_UNNORMALIZED { return true; } } @@ -485,7 +510,7 @@ impl { - INSTANTIATE_LHS_WITH_INFER + HANDLE_LHS < HANDLE_UNNORMALIZED || match rhs.kind() { ty::ConstKind::Param(rhs) => lhs == rhs, _ => false, diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 19c59df0604c3..c62c7bfb27491 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -146,6 +146,14 @@ bitflags::bitflags! { /// Does this have a `Bound(BoundVarIndexKind::Canonical, _)`? const HAS_CANONICAL_BOUND = 1 << 26; + + /// Does this have a `IsRigid::Yes` for some aliases? + const HAS_RIGID_ALIAS = 1 << 27; + + /// Does this have a `IsRigid::No` for some aliases? + /// + /// We have both flags because both can be true at the same time. + const HAS_NON_RIGID_ALIAS = 1 << 28; } } @@ -302,6 +310,10 @@ impl FlagComputation { ty::Opaque { .. } => TypeFlags::HAS_TY_OPAQUE, ty::Inherent { .. } => TypeFlags::HAS_TY_INHERENT, }); + match alias.is_rigid { + ty::IsRigid::Yes => self.add_flags(TypeFlags::HAS_RIGID_ALIAS), + ty::IsRigid::No => self.add_flags(TypeFlags::HAS_NON_RIGID_ALIAS), + } self.add_alias_ty(alias); } @@ -468,6 +480,7 @@ impl FlagComputation { ty::ConstKind::Unevaluated(uv) => { self.add_args(uv.args.as_slice()); self.add_flags(TypeFlags::HAS_CT_PROJECTION); + self.add_flags(TypeFlags::HAS_NON_RIGID_ALIAS); } ty::ConstKind::Infer(infer) => match infer { ty::InferConst::Fresh(_) => self.add_flags(TypeFlags::HAS_CT_FRESH), diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index 0fe68b5256691..d62c27517f380 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -554,3 +554,56 @@ where if c.has_regions() { c.super_fold_with(self) } else { c } } } + +pub fn reset_rigid_aliases(cx: I, value: T) -> T +where + T: TypeFoldable, +{ + if !value.has_rigid_aliases() { + return value; + } + + let mut folder = RigidnessFolder { cx }; + value.fold_with(&mut folder) +} + +struct RigidnessFolder { + cx: I, +} + +impl TypeFolder for RigidnessFolder { + #[inline] + fn cx(&self) -> I { + self.cx + } + + fn fold_binder>(&mut self, t: ty::Binder) -> ty::Binder { + if t.has_rigid_aliases() { t.super_fold_with(self) } else { t } + } + + fn fold_ty(&mut self, t: I::Ty) -> I::Ty { + if !t.has_rigid_aliases() { + return t; + } + + match t.kind() { + ty::Alias(alias_ty) if alias_ty.is_rigid == ty::IsRigid::Yes => { + let alias_ty = alias_ty.fold_with(self); + I::Ty::new_alias(self.cx(), alias_ty.to_non_rigid()) + } + _ => t.super_fold_with(self), + } + } + + fn fold_const(&mut self, c: I::Const) -> I::Const { + if c.has_rigid_aliases() { c.super_fold_with(self) } else { c } + } + + fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate { + if p.has_rigid_aliases() { p.super_fold_with(self) } else { p } + } + + fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses { + if c.has_rigid_aliases() { c.super_fold_with(self) } else { c } + } +} diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 8859ab7c037b0..8d94db1831d69 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -62,7 +62,12 @@ pub trait Ty>: ) -> Self { Self::new_alias( interner, - ty::AliasTy::new_from_args(interner, ty::AliasTyKind::Projection { def_id }, args), + ty::AliasTy::new_from_args( + interner, + ty::AliasTyKind::Projection { def_id }, + args, + ty::IsRigid::No, + ), ) } @@ -73,7 +78,12 @@ pub trait Ty>: ) -> Self { Self::new_alias( interner, - ty::AliasTy::new(interner, ty::AliasTyKind::Projection { def_id }, args), + ty::AliasTy::new( + interner, + ty::AliasTyKind::Projection { def_id }, + args, + ty::IsRigid::No, + ), ) } diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 301cf7dbf1087..a86cfb47c6e3a 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -12,7 +12,7 @@ use crate::inherent::*; use crate::lift::Lift; use crate::upcast::{Upcast, UpcastFrom}; use crate::visit::TypeVisitableExt as _; -use crate::{self as ty, AliasTyKind, Interner}; +use crate::{self as ty, AliasTyKind, Interner, IsRigid}; /// `A: 'region` #[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, A)] @@ -526,6 +526,7 @@ impl ExistentialProjection { interner, interner.alias_term_kind_from_def_id(self.def_id.into()), [self_ty.into()].iter().chain(self.args.iter()), + IsRigid::No, ), term: self.term, } @@ -685,6 +686,10 @@ pub struct AliasTerm { #[type_visitable(ignore)] pub kind: AliasTermKind, + #[type_foldable(identity)] + #[type_visitable(ignore)] + pub is_rigid: IsRigid, + /// This field exists to prevent the creation of `AliasTerm` without using [`AliasTerm::new_from_args`]. #[derive_where(skip(Debug))] _use_alias_term_new_instead: (), @@ -697,28 +702,35 @@ impl AliasTerm { interner: I, kind: AliasTermKind, args: I::GenericArgs, + is_rigid: IsRigid, ) -> AliasTerm { interner.debug_assert_args_compatible(kind.def_id(), args); - AliasTerm { kind, args, _use_alias_term_new_instead: () } + AliasTerm { kind, args, is_rigid, _use_alias_term_new_instead: () } } pub fn new( interner: I, kind: AliasTermKind, args: impl IntoIterator>, + is_rigid: IsRigid, ) -> AliasTerm { let args = interner.mk_args_from_iter(args.into_iter().map(Into::into)); - Self::new_from_args(interner, kind, args) + Self::new_from_args(interner, kind, args, is_rigid) } - pub fn new_from_def_id(interner: I, def_id: I::DefId, args: I::GenericArgs) -> AliasTerm { + pub fn new_from_def_id( + interner: I, + def_id: I::DefId, + args: I::GenericArgs, + is_rigid: IsRigid, + ) -> AliasTerm { let kind = interner.alias_term_kind_from_def_id(def_id); - Self::new_from_args(interner, kind, args) + Self::new_from_args(interner, kind, args, is_rigid) } pub fn from_unevaluated_const(interner: I, ct: ty::UnevaluatedConst) -> Self { let kind = interner.alias_term_kind_from_def_id(ct.def.into()); - AliasTerm::new_from_args(interner, kind, ct.args) + AliasTerm::new_from_args(interner, kind, ct.args, ct.is_rigid) } pub fn expect_ty(self, interner: I) -> ty::AliasTy { @@ -734,7 +746,12 @@ impl AliasTerm { panic!("Cannot turn `{}` into `AliasTy`", kind.descr()) } }; - ty::AliasTy { kind, args: self.args, _use_alias_ty_new_instead: () } + ty::AliasTy { + kind, + args: self.args, + is_rigid: self.is_rigid, + _use_alias_ty_new_instead: (), + } } pub fn expect_ct(self, interner: I) -> ty::UnevaluatedConst { @@ -750,7 +767,7 @@ impl AliasTerm { panic!("Cannot turn `{}` into `UnevaluatedConst`", kind.descr()) } }; - ty::UnevaluatedConst { def, args: self.args } + ty::UnevaluatedConst { def, args: self.args, is_rigid: self.is_rigid } } // FIXME: remove this function (access the field instead) @@ -765,7 +782,11 @@ impl AliasTerm { pub fn to_term(self, interner: I) -> I::Term { let unevaluated_const = |def_id| { - I::Const::new_unevaluated(interner, ty::UnevaluatedConst::new(def_id, self.args)).into() + I::Const::new_unevaluated( + interner, + ty::UnevaluatedConst::new(def_id, self.args, self.is_rigid), + ) + .into() }; let alias_ty_kind = match self.kind(interner) { AliasTermKind::FreeConst { def_id } => return unevaluated_const(def_id.into()), @@ -779,12 +800,23 @@ impl AliasTerm { AliasTermKind::FreeTy { def_id } => ty::Free { def_id }, }; - Ty::new_alias(interner, ty::AliasTy::new_from_args(interner, alias_ty_kind, self.args)) - .into() + Ty::new_alias( + interner, + ty::AliasTy::new_from_args(interner, alias_ty_kind, self.args, self.is_rigid), + ) + .into() } pub fn with_args(self, interner: I, args: I::GenericArgs) -> Self { - Self::new_from_args(interner, self.kind, args) + Self::new_from_args(interner, self.kind, args, self.is_rigid) + } + + pub fn to_rigid(self) -> AliasTerm { + AliasTerm { is_rigid: IsRigid::Yes, ..self } + } + + pub fn to_non_rigid(self) -> AliasTerm { + AliasTerm { is_rigid: IsRigid::No, ..self } } } @@ -799,6 +831,7 @@ impl AliasTerm { interner, self.kind, [self_ty.into()].into_iter().chain(self.args.iter().skip(1)), + self.is_rigid, ) } @@ -880,6 +913,7 @@ impl From> for AliasTerm { AliasTerm { args: ty.args, kind: AliasTermKind::from(ty.kind), + is_rigid: ty.is_rigid, _use_alias_term_new_instead: (), } } diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 51de99e92fcad..d8e9e573c25d7 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -219,13 +219,14 @@ impl Relate for ty::AliasTy { b.kind.def_id(), ))) } else { + debug_assert_eq!(a.is_rigid, b.is_rigid); let cx = relation.cx(); let args = if let Some(variances) = cx.opt_alias_variances(a.kind) { relate_args_with_variances(relation, variances, a.args, b.args)? } else { relate_args_invariantly(relation, a.args, b.args)? }; - Ok(ty::AliasTy::new_from_args(relation.cx(), a.kind, args)) + Ok(ty::AliasTy::new_from_args(relation.cx(), a.kind, args, a.is_rigid)) } } } @@ -503,7 +504,8 @@ pub fn structurally_relate_tys>( } // Alias tend to mostly already be handled downstream due to normalization. - (ty::Alias(a), ty::Alias(b)) => { + // FIXME: doubtful about allowing non rigid relating. + (ty::Alias(a), ty::Alias(b)) if a.is_rigid == b.is_rigid => { let alias_ty = relation.relate(a, b)?; Ok(Ty::new_alias(cx, alias_ty)) } @@ -591,7 +593,9 @@ pub fn structurally_relate_consts>( // While this is slightly incorrect, it shouldn't matter for `min_const_generics` // and is the better alternative to waiting until `generic_const_exprs` can // be stabilized. - (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => { + (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) + if au.def == bu.def && au.is_rigid == bu.is_rigid => + { // FIXME(mgca): remove this if cfg!(debug_assertions) { let a_ty = cx.type_of(au.def.into()).instantiate(cx, au.args).skip_norm_wip(); @@ -605,7 +609,10 @@ pub fn structurally_relate_consts>( au.args, bu.args, )?; - return Ok(Const::new_unevaluated(cx, ty::UnevaluatedConst { def: au.def, args })); + return Ok(Const::new_unevaluated( + cx, + ty::UnevaluatedConst { def: au.def, args, is_rigid: au.is_rigid }, + )); } (ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => { let expr = relation.relate(ae, be)?; diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 6f3cea27cafdb..8bb042c96f0f8 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -88,6 +88,17 @@ impl AliasTyKind { } } +#[derive(Debug, Clone, Copy, Hash, PartialEq)] +#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)] +#[cfg_attr( + feature = "nightly", + derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext) +)] +pub enum IsRigid { + Yes, + No, +} + /// Defines the kinds of types used by the type system. /// /// Types written by the user start out as `hir::TyKind` and get @@ -459,6 +470,10 @@ pub struct AliasTy { #[type_visitable(ignore)] pub kind: AliasTyKind, + #[type_foldable(identity)] + #[type_visitable(ignore)] + pub is_rigid: IsRigid, + /// This field exists to prevent the creation of `AliasTy` without using [`AliasTy::new_from_args`]. #[derive_where(skip(Debug))] pub(crate) _use_alias_ty_new_instead: (), @@ -467,18 +482,24 @@ pub struct AliasTy { impl Eq for AliasTy {} impl AliasTy { - pub fn new_from_args(interner: I, kind: AliasTyKind, args: I::GenericArgs) -> AliasTy { + pub fn new_from_args( + interner: I, + kind: AliasTyKind, + args: I::GenericArgs, + is_rigid: IsRigid, + ) -> AliasTy { interner.debug_assert_args_compatible(kind.def_id(), args); - AliasTy { kind, args, _use_alias_ty_new_instead: () } + AliasTy { kind, args, is_rigid, _use_alias_ty_new_instead: () } } pub fn new( interner: I, kind: AliasTyKind, args: impl IntoIterator>, + is_rigid: IsRigid, ) -> AliasTy { let args = interner.mk_args_from_iter(args.into_iter().map(Into::into)); - Self::new_from_args(interner, kind, args) + Self::new_from_args(interner, kind, args, is_rigid) } /// Whether this alias type is an opaque. @@ -489,6 +510,14 @@ impl AliasTy { pub fn to_ty(self, interner: I) -> I::Ty { Ty::new_alias(interner, self) } + + pub fn to_rigid(self) -> AliasTy { + AliasTy { is_rigid: IsRigid::Yes, ..self } + } + + pub fn to_non_rigid(self) -> AliasTy { + AliasTy { is_rigid: IsRigid::No, ..self } + } } /// The following methods work only with (trait) associated type projections. @@ -503,6 +532,7 @@ impl AliasTy { interner, self.kind, [self_ty.into()].into_iter().chain(self.args.iter().skip(1)), + self.is_rigid, ) } diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 492c37481298b..843fdf03fabd2 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -363,6 +363,16 @@ pub trait TypeVisitableExt: TypeVisitable { fn has_non_region_error(&self) -> bool { self.has_type_flags(TypeFlags::HAS_NON_REGION_ERROR) } + + /// True if an alias has `IsRigid::Yes`. Used for skipping normalization. + fn has_rigid_aliases(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RIGID_ALIAS) + } + + /// True if an alias has `IsRigid::No`. + fn has_non_rigid_aliases(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_NON_RIGID_ALIAS) + } } impl> TypeVisitableExt for T { diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index b384d58a02f83..f92c91106b43e 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -1052,6 +1052,7 @@ pub fn make_projection<'tcx>( tcx, ty::AliasTyKind::new_from_def_id(tcx, assoc_item.def_id), args, + ty::IsRigid::No, )) } helper( diff --git a/tests/ui/README.md b/tests/ui/README.md index 39402f78bb5ec..1ab22a65ce507 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -109,10 +109,6 @@ Tests focused on associated types. If the associated type is not in a trait defi See [Associated Types | Reference](https://doc.rust-lang.org/reference/items/associated-items.html#associated-types). -## `tests/ui/assumptions_on_binders`: -Zassumptions-on-binders - -Tests focused on the -Zassumptions-on-binders flag. - ## `tests/ui/async-await`: Async/Await Tests for the async/await related features. E.g. async functions, await expressions, and their interaction with other language features. diff --git a/tests/ui/assumptions_on_binders/alias_outlives.rs b/tests/ui/assumptions_on_binders/alias_outlives.rs deleted file mode 100644 index c234773fb10d8..0000000000000 --- a/tests/ui/assumptions_on_binders/alias_outlives.rs +++ /dev/null @@ -1,42 +0,0 @@ -//@ compile-flags: -Znext-solver -Zassumptions-on-binders - -// test that a `::Assoc: '!a_u1` constraint is considered to be satisfied -// if there's a `T::Assoc: 'static` assumption in the root universe and if not that it is -// an error :) - -#![feature(generic_const_items)] - -trait AliasHaver { - type Assoc; -} - -trait Trait<'a> {} -impl<'a, T: 'a> Trait<'a> for T {} - -struct ReqTrait Trait<'a>>(T); - -fn borrowck_env_pass<'a, T: AliasHaver>() -where - ::Assoc: 'static, -{ - let _: ReqTrait; -} - -fn borrowck_env_fail<'a, T: AliasHaver>() -//~^ ERROR: unsatisfied lifetime constraint from -Zassumptions-on-binders -where - ::Assoc: 'a, -{ - let _: ReqTrait; -} - -const REGIONCK_ENV_PASS<'a, T: AliasHaver>: ReqTrait = todo!() -where - ::Assoc: 'static; - -const REGIONCK_ENV_FAIL<'a, T: AliasHaver>: ReqTrait = todo!() -//~^ ERROR: unsatisfied lifetime constraint from -Zassumptions-on-binders -where - ::Assoc: 'a; - -fn main() {} diff --git a/tests/ui/assumptions_on_binders/alias_outlives.stderr b/tests/ui/assumptions_on_binders/alias_outlives.stderr deleted file mode 100644 index bd3819798737d..0000000000000 --- a/tests/ui/assumptions_on_binders/alias_outlives.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error: unsatisfied lifetime constraint from -Zassumptions-on-binders :3 - --> $DIR/alias_outlives.rs:37:1 - | -LL | const REGIONCK_ENV_FAIL<'a, T: AliasHaver>: ReqTrait = todo!() - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: meoow :c - -error: unsatisfied lifetime constraint from -Zassumptions-on-binders :3 - --> $DIR/alias_outlives.rs:25:1 - | -LL | / fn borrowck_env_fail<'a, T: AliasHaver>() -LL | | -LL | | where -LL | | ::Assoc: 'a, - | |_________________________________^ - | - = note: meoow :c - -error: aborting due to 2 previous errors - diff --git a/tests/ui/assumptions_on_binders/implied_higher_ranked_alias_outlives_assumption.rs b/tests/ui/assumptions_on_binders/implied_higher_ranked_alias_outlives_assumption.rs deleted file mode 100644 index c0cb6ce416aed..0000000000000 --- a/tests/ui/assumptions_on_binders/implied_higher_ranked_alias_outlives_assumption.rs +++ /dev/null @@ -1,53 +0,0 @@ -//@ compile-flags: -Znext-solver -Zassumptions-on-binders -//@ check-pass - -#![feature(generic_const_items)] - -// sorry for writing this -// - boxy - -// for<'a> where(for<'d> ::Assoc: 'c) { -// for<'b> { -// >::Assoc: 'c -// } -// -// rewritten to: for<'b> >::Assoc: 'c -// } -// rewritten to: true (via assumption) -// rewritting to `for<'a, 'b> >::Assoc: 'c` would be wrong - -trait Trait<'a, 'b> { - type Assoc; -} - -struct ImpliedBound<'a, 'c, T: for<'b> Trait<'a, 'b>>(T, &'a (), &'c ()) -where - for<'b> >::Assoc: 'c,; - -trait InnerBinder<'a, 'b, 'c> {} -impl<'a, 'b, 'c, S> InnerBinder<'a, 'b, 'c> for S -where - S: Trait<'a, 'b>, - >::Assoc: 'c {} - -trait OuterBinder<'a, 'c, T0> {} -impl<'a, 'c, T0, S> OuterBinder<'a, 'c, T0> for S -where - for<'b> S: InnerBinder<'a, 'b, 'c>, {} - -struct ReqTrait<'c, T>(&'c (), T) -where - for<'a> T: OuterBinder<'a, 'c, ImpliedBound<'a, 'c, T>>,; - -fn borrowck_env<'c, T>() -where - T: for<'a, 'b> Trait<'a, 'b> -{ - let _: ReqTrait<'c, T>; -} - -const REGIONCK_ENV<'c, T>: ReqTrait<'c, T> = todo!() -where - T: for<'a, 'b> Trait<'a, 'b>; - -fn main() {} diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr index f609dcab752af..e14b7a110e436 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr @@ -14,7 +14,7 @@ help: consider giving this pattern a type, where the value of const parameter `N LL | let (mut arr, mut arr_with_weird_len): ([_; N], _) = free(); | +++++++++++++ -error[E0271]: type mismatch resolving `10 == 2` +error[E0271]: type mismatch resolving `FREE::<10> == 2` --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:35:45 | LL | let (mut arr, mut arr_with_weird_len) = free(); @@ -36,11 +36,14 @@ help: consider giving this pattern a type, where the value of const parameter `N LL | let (mut arr, mut arr_with_weird_len): ([_; N], _) = proj(); | +++++++++++++ -error[E0271]: type mismatch resolving `10 == 2` +error[E0271]: type mismatch resolving `::PROJ::<10> == 2` --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:52:45 | LL | let (mut arr, mut arr_with_weird_len) = proj(); - | ^^^^^^ types differ + | ^^^^^^ expected `2`, found `10` + | + = note: expected constant `2` + found constant `10` error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs index 72952940b1c12..12e92d5530032 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs @@ -33,7 +33,7 @@ fn test_free() { fn test_free_mismatch() { let (mut arr, mut arr_with_weird_len) = free(); - //[next]~^ ERROR type mismatch resolving `10 == 2` + //[next]~^ ERROR type mismatch resolving `FREE::<10> == 2` arr_with_weird_len = [(); 2]; arr = [(); 10]; } @@ -50,7 +50,7 @@ fn test_proj() { fn test_proj_mismatch() { let (mut arr, mut arr_with_weird_len) = proj(); - //[next]~^ ERROR type mismatch resolving `10 == 2` + //[next]~^ ERROR type mismatch resolving `::PROJ::<10> == 2` arr_with_weird_len = [(); 2]; arr = [(); 10]; } diff --git a/tests/ui/const-generics/generic_const_exprs/negative-coherence-ice-140609.rs b/tests/ui/const-generics/generic_const_exprs/negative-coherence-ice-140609.rs deleted file mode 100644 index 1b02b874ed898..0000000000000 --- a/tests/ui/const-generics/generic_const_exprs/negative-coherence-ice-140609.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ check-pass -#![feature(with_negative_coherence)] -#![feature(generic_const_exprs)] -#![allow(incomplete_features)] -#![crate_type = "lib"] -trait Trait {} -struct A; - -trait C {} - -impl Trait for E where A<{ D <= 2 }>: FnOnce(&isize) {} -struct E; - -impl Trait for E where A<{ D <= 2 }>: C {} diff --git a/tests/ui/const-generics/generic_const_exprs/specialization-fuzzing-ice-133639.rs b/tests/ui/const-generics/generic_const_exprs/specialization-fuzzing-ice-133639.rs deleted file mode 100644 index d605c83239b27..0000000000000 --- a/tests/ui/const-generics/generic_const_exprs/specialization-fuzzing-ice-133639.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ check-pass - -// Regression test for #133639. - -#![feature(with_negative_coherence)] -#![feature(min_specialization)] -#![feature(generic_const_exprs)] - -#![crate_type = "lib"] -trait Trait {} -struct A; - -trait C {} - -impl Trait for E where A<{ D <= 2 }>: C {} -struct E; - -impl Trait for E where A<{ D <= 2 }>: C {} diff --git a/tests/ui/const-generics/mgca/free-const-recursive.rs b/tests/ui/const-generics/mgca/free-const-recursive.rs index 8d75c1a941a77..0cbe848340516 100644 --- a/tests/ui/const-generics/mgca/free-const-recursive.rs +++ b/tests/ui/const-generics/mgca/free-const-recursive.rs @@ -6,7 +6,7 @@ type const A: () = A; //~^ ERROR type mismatch resolving `A normalizes-to _` -//~| ERROR the constant `A` is not of type `()` +//~| ERROR type mismatch resolving `A normalizes-to _` fn main() { A; diff --git a/tests/ui/const-generics/mgca/free-const-recursive.stderr b/tests/ui/const-generics/mgca/free-const-recursive.stderr index d0f10275b40d2..20bcd2dcc93f3 100644 --- a/tests/ui/const-generics/mgca/free-const-recursive.stderr +++ b/tests/ui/const-generics/mgca/free-const-recursive.stderr @@ -4,11 +4,13 @@ error[E0271]: type mismatch resolving `A normalizes-to _` LL | type const A: () = A; | ^^^^^^^^^^^^^^^^ types differ -error: the constant `A` is not of type `()` +error[E0271]: type mismatch resolving `A normalizes-to _` --> $DIR/free-const-recursive.rs:7:1 | LL | type const A: () = A; - | ^^^^^^^^^^^^^^^^ expected `()`, found a different `()` + | ^^^^^^^^^^^^^^^^ types differ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/projection-const-recursive.rs b/tests/ui/const-generics/mgca/projection-const-recursive.rs index c9b5039b5fd0b..15112517249a8 100644 --- a/tests/ui/const-generics/mgca/projection-const-recursive.rs +++ b/tests/ui/const-generics/mgca/projection-const-recursive.rs @@ -1,6 +1,6 @@ //! See also //@ check-fail -//@compile-flags: -Znext-solver=globally --emit=obj +//@ compile-flags: -Znext-solver=globally --emit=obj #![feature(min_generic_const_args)] #![expect(incomplete_features)] @@ -11,7 +11,7 @@ trait Trait { impl Trait for () { type const A: () = <() as Trait>::A; //~^ ERROR type mismatch resolving `<() as Trait>::A normalizes-to _` - //~| ERROR the constant `<() as Trait>::A` is not of type `()` + //~| ERROR type mismatch resolving `<() as Trait>::A normalizes-to _` } fn main() { diff --git a/tests/ui/const-generics/mgca/projection-const-recursive.stderr b/tests/ui/const-generics/mgca/projection-const-recursive.stderr index d9c60102c3184..8bc5afc81f33c 100644 --- a/tests/ui/const-generics/mgca/projection-const-recursive.stderr +++ b/tests/ui/const-generics/mgca/projection-const-recursive.stderr @@ -4,11 +4,13 @@ error[E0271]: type mismatch resolving `<() as Trait>::A normalizes-to _` LL | type const A: () = <() as Trait>::A; | ^^^^^^^^^^^^^^^^ types differ -error: the constant `<() as Trait>::A` is not of type `()` +error[E0271]: type mismatch resolving `<() as Trait>::A normalizes-to _` --> $DIR/projection-const-recursive.rs:12:5 | LL | type const A: () = <() as Trait>::A; - | ^^^^^^^^^^^^^^^^ expected `()`, found a different `()` + | ^^^^^^^^^^^^^^^^ types differ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/coroutine/delayed-obligations-emit.next.stderr b/tests/ui/coroutine/delayed-obligations-emit.next.stderr index 3a3663398c9a7..af7dfc75963c2 100644 --- a/tests/ui/coroutine/delayed-obligations-emit.next.stderr +++ b/tests/ui/coroutine/delayed-obligations-emit.next.stderr @@ -4,6 +4,7 @@ error[E0275]: overflow evaluating the requirement `{async block@$DIR/delayed-obl LL | spawn(async { build_dependencies().await }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`delayed_obligations_emit`) note: required by a bound in `spawn` --> $DIR/delayed-obligations-emit.rs:31:13 | diff --git a/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr b/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr index 31d74d1c022a1..26e682dfb7a7c 100644 --- a/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr +++ b/tests/ui/higher-ranked/trait-bounds/rigid-equate-projections-in-higher-ranked-fn-signature.next.stderr @@ -1,8 +1,8 @@ -error[E0284]: type annotations needed: cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc normalizes-to >::Assoc` - --> $DIR/rigid-equate-projections-in-higher-ranked-fn-signature.rs:27:50 +error[E0284]: type annotations needed: cannot normalize `<_ as Trait<'a>>::Assoc` + --> $DIR/rigid-equate-projections-in-higher-ranked-fn-signature.rs:27:12 | LL | let _: for<'a> fn(<_ as Trait<'a>>::Assoc) = foo::(); - | ^^^^^^^^^^ cannot satisfy `for<'a> <_ as Trait<'a>>::Assoc normalizes-to >::Assoc` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot normalize `<_ as Trait<'a>>::Assoc` error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs index c87c8e90d741b..b63e595fd5d54 100644 --- a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs +++ b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.rs @@ -15,4 +15,5 @@ struct W(T); fn hello(_: W>) {} //~^ ERROR: the trait bound `usize: Foo` is not satisfied //~| ERROR: the trait bound `usize: Foo` is not satisfied +//~| ERROR: the type `W>` is not well-formed fn main() {} diff --git a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr index dec94730df615..09418b656f8ac 100644 --- a/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr +++ b/tests/ui/impl-trait/in-trait/alias-bounds-when-not-wf.stderr @@ -15,6 +15,12 @@ note: required by a bound in `A` LL | type A = T; | ^^^ required by this bound in `A` +error: the type `W>` is not well-formed + --> $DIR/alias-bounds-when-not-wf.rs:15:13 + | +LL | fn hello(_: W>) {} + | ^^^^^^^^^^^ + error[E0277]: the trait bound `usize: Foo` is not satisfied --> $DIR/alias-bounds-when-not-wf.rs:15:13 | @@ -27,6 +33,6 @@ help: this trait has no implementations, consider adding one LL | trait Foo {} | ^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/async.fail.stderr b/tests/ui/traits/next-solver/async.fail.stderr index a76a10d20ee8b..bc89842d16a14 100644 --- a/tests/ui/traits/next-solver/async.fail.stderr +++ b/tests/ui/traits/next-solver/async.fail.stderr @@ -1,8 +1,8 @@ -error[E0271]: type mismatch resolving `() == i32` +error[E0271]: expected `{async block@$DIR/async.rs:12:17: 12:22}` to be a future that resolves to `i32`, but it resolves to `()` --> $DIR/async.rs:12:17 | LL | needs_async(async {}); - | ----------- ^^^^^^^^ types differ + | ----------- ^^^^^^^^ expected `i32`, found `()` | | | required by a bound introduced by this call | diff --git a/tests/ui/traits/next-solver/async.rs b/tests/ui/traits/next-solver/async.rs index 34c0ed02eeb12..fded774354759 100644 --- a/tests/ui/traits/next-solver/async.rs +++ b/tests/ui/traits/next-solver/async.rs @@ -10,7 +10,7 @@ fn needs_async(_: impl Future) {} #[cfg(fail)] fn main() { needs_async(async {}); - //[fail]~^ ERROR type mismatch resolving `() == i32` + //[fail]~^ ERROR expected `{async block@$DIR/async.rs:12:17: 12:22}` to be a future that resolves to `i32`, but it resolves to `()` } #[cfg(pass)] diff --git a/tests/ui/traits/next-solver/coercion/non-wf-in-coerce-pointers.rs b/tests/ui/traits/next-solver/coercion/non-wf-in-coerce-pointers.rs index bd33e3c2f47ee..0b63bb3261db7 100644 --- a/tests/ui/traits/next-solver/coercion/non-wf-in-coerce-pointers.rs +++ b/tests/ui/traits/next-solver/coercion/non-wf-in-coerce-pointers.rs @@ -7,6 +7,7 @@ trait Wf { struct S { f: &'static <() as Wf>::Assoc, //~^ ERROR the trait bound `(): Wf` is not satisfied + //~| ERROR the type `&'static <() as Wf>::Assoc` is not well-formed } fn main() { diff --git a/tests/ui/traits/next-solver/coercion/non-wf-in-coerce-pointers.stderr b/tests/ui/traits/next-solver/coercion/non-wf-in-coerce-pointers.stderr index d484a0a1c4c28..2f7307eb96b77 100644 --- a/tests/ui/traits/next-solver/coercion/non-wf-in-coerce-pointers.stderr +++ b/tests/ui/traits/next-solver/coercion/non-wf-in-coerce-pointers.stderr @@ -10,8 +10,14 @@ help: this trait has no implementations, consider adding one LL | trait Wf { | ^^^^^^^^ +error: the type `&'static <() as Wf>::Assoc` is not well-formed + --> $DIR/non-wf-in-coerce-pointers.rs:8:8 + | +LL | f: &'static <() as Wf>::Assoc, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0277]: the trait bound `(): Wf` is not satisfied - --> $DIR/non-wf-in-coerce-pointers.rs:14:18 + --> $DIR/non-wf-in-coerce-pointers.rs:15:18 | LL | let y: &() = x.f; | ^^^ the trait `Wf` is not implemented for `()` @@ -22,6 +28,6 @@ help: this trait has no implementations, consider adding one LL | trait Wf { | ^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs index 914773c82196a..d1cdb3164d428 100644 --- a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs +++ b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs @@ -14,7 +14,7 @@ fn foo() where T: for<'a> Proj<'a, Assoc = for<'b> fn(>::Assoc)>, (): Trait<>::Assoc> - //~^ ERROR: overflow evaluating the requirement `(): Trait<>::Assoc>` + //~^ ERROR: overflow evaluating the requirement `(): Trait fn(>::Assoc)>` { } diff --git a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr index e2ee83cfadbef..405081614a565 100644 --- a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr +++ b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr @@ -1,4 +1,4 @@ -error[E0275]: overflow evaluating the requirement `(): Trait<>::Assoc>` +error[E0275]: overflow evaluating the requirement `(): Trait fn(>::Assoc)>` --> $DIR/find-param-recursion-issue-152716.rs:16:9 | LL | (): Trait<>::Assoc> diff --git a/tests/ui/traits/next-solver/lazy-nested-obligations-2.next.stderr b/tests/ui/traits/next-solver/lazy-nested-obligations-2.next.stderr index 462544b405218..cc11aa018161a 100644 --- a/tests/ui/traits/next-solver/lazy-nested-obligations-2.next.stderr +++ b/tests/ui/traits/next-solver/lazy-nested-obligations-2.next.stderr @@ -1,14 +1,20 @@ -error[E0271]: type mismatch resolving `fn(&str) == fn(&str) {f}` +error[E0271]: type mismatch resolving `::F == fn(&str) {f}` --> $DIR/lazy-nested-obligations-2.rs:20:21 | LL | let _: V = V(f); - | ^^^^ types differ + | ^^^^ expected fn item, found fn pointer + | + = note: expected fn item `for<'a> fn(&'a _) {f}` + found fn pointer `for<'a> fn(&'a _)` -error[E0271]: type mismatch resolving `fn(&str) == fn(&str) {f}` +error[E0271]: type mismatch resolving `::F == fn(&str) {f}` --> $DIR/lazy-nested-obligations-2.rs:27:22 | LL | let _: E3 = E3::Var(f); - | ^^^^^^^^^^ types differ + | ^^^^^^^^^^ expected fn item, found fn pointer + | + = note: expected fn item `for<'a> fn(&'a _) {f}` + found fn pointer `for<'a> fn(&'a _)` error: aborting due to 2 previous errors diff --git a/tests/ui/traits/next-solver/more-object-bound.rs b/tests/ui/traits/next-solver/more-object-bound.rs index 1dad1903a649d..3d3fdc926f658 100644 --- a/tests/ui/traits/next-solver/more-object-bound.rs +++ b/tests/ui/traits/next-solver/more-object-bound.rs @@ -10,7 +10,7 @@ trait Trait: SuperTrait::B> {} fn transmute(x: A) -> B { foo::>(x) - //~^ ERROR type mismatch resolving `A == B` + //~^ ERROR type mismatch resolving ` as SuperTrait>::A == B` } fn foo(x: T::A) -> B diff --git a/tests/ui/traits/next-solver/more-object-bound.stderr b/tests/ui/traits/next-solver/more-object-bound.stderr index 7d279ed64282b..ccbf19ae4d96c 100644 --- a/tests/ui/traits/next-solver/more-object-bound.stderr +++ b/tests/ui/traits/next-solver/more-object-bound.stderr @@ -1,9 +1,17 @@ -error[E0271]: type mismatch resolving `A == B` +error[E0271]: type mismatch resolving ` as SuperTrait>::A == B` --> $DIR/more-object-bound.rs:12:17 | +LL | fn transmute(x: A) -> B { + | - - expected type parameter + | | + | found type parameter LL | foo::>(x) - | ^^^^^^^^^^^^^^^^^^^^^^^ types differ + | ^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `B`, found type parameter `A` | + = note: expected type parameter `B` + found type parameter `A` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters = note: required because it appears within the type `dyn Trait` note: required by a bound in `foo` --> $DIR/more-object-bound.rs:18:8 diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr index ecd86dba97994..b166bd0ccb92d 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr @@ -45,9 +45,43 @@ LL | trait A { LL | fn f() | ^ this trait's associated function doesn't have the requirement `_: A` -error[E0275]: overflow evaluating the requirement `<() as A>::Assoc: A` +error[E0275]: overflow evaluating the requirement `<() as A>::Assoc == _` + --> $DIR/normalize-param-env-2.rs:24:22 + | +LL | Self::Assoc: A, + | ^^^^ + | +note: required by a bound in `A` + --> $DIR/normalize-param-env-2.rs:9:1 + | +LL | / trait A { +LL | | type Assoc; +LL | | +LL | | fn f() +... | +LL | | } + | |_^ required by this bound in `A` + +error[E0275]: overflow evaluating the requirement `<() as A>::Assoc == _` + --> $DIR/normalize-param-env-2.rs:24:22 + | +LL | Self::Assoc: A, + | ^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0283]: type annotations needed --> $DIR/normalize-param-env-2.rs:24:22 | +LL | Self::Assoc: A, + | ^^^^ cannot infer type + | +note: multiple `impl`s or `where` clauses satisfying `_: A` found + --> $DIR/normalize-param-env-2.rs:19:1 + | +LL | impl A for () { + | ^^^^^^^^^^^^^^^^^^^ +... LL | Self::Assoc: A, | ^^^^ @@ -92,7 +126,7 @@ LL | where LL | Self::Assoc: A, | ^^^^ required by this bound in `A::f` -error: aborting due to 9 previous errors +error: aborting due to 11 previous errors Some errors have detailed explanations: E0275, E0283. For more information about an error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr index 47d38365e970e..a6cb9e4b4dc64 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr @@ -1,4 +1,18 @@ -error[E0275]: overflow evaluating the requirement `::Assoc: Trait` +error[E0275]: overflow evaluating the requirement `::Assoc == _` + --> $DIR/normalize-param-env-4.rs:19:26 + | +LL | ::Assoc: Trait, + | ^^^^^ + | +note: required by a bound in `Trait` + --> $DIR/normalize-param-env-4.rs:7:1 + | +LL | / trait Trait { +LL | | type Assoc; +LL | | } + | |_^ required by this bound in `Trait` + +error[E0275]: overflow evaluating the requirement `::Assoc == _` --> $DIR/normalize-param-env-4.rs:19:26 | LL | ::Assoc: Trait, @@ -22,6 +36,6 @@ note: required by a bound in `impls_trait` LL | fn impls_trait() {} | ^^^^^ required by this bound in `impls_trait` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs index c61fbef05b224..8dc27c0da605a 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs @@ -13,7 +13,7 @@ fn needs_bar() {} fn test::Assoc2> + Foo2::Assoc1>>() { needs_bar::(); - //~^ ERROR: the trait bound `::Assoc2: Bar` is not satisfied + //~^ ERROR: the trait bound `::Assoc1: Bar` is not satisfied } fn main() {} diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr index c4be47e3520da..6f5111a6193ca 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `::Assoc2: Bar` is not satisfied +error[E0277]: the trait bound `::Assoc1: Bar` is not satisfied --> $DIR/recursive-self-normalization-2.rs:15:17 | LL | needs_bar::(); - | ^^^^^^^^^ the trait `Bar` is not implemented for `::Assoc2` + | ^^^^^^^^^ the trait `Bar` is not implemented for `::Assoc1` | note: required by a bound in `needs_bar` --> $DIR/recursive-self-normalization-2.rs:12:17 @@ -11,7 +11,7 @@ LL | fn needs_bar() {} | ^^^ required by this bound in `needs_bar` help: consider further restricting the associated type | -LL | fn test::Assoc2> + Foo2::Assoc1>>() where ::Assoc2: Bar { +LL | fn test::Assoc2> + Foo2::Assoc1>>() where ::Assoc1: Bar { | ++++++++++++++++++++++++++++++ error: aborting due to 1 previous error diff --git a/tests/ui/traits/normalize/normalize-diverging-alias-in-struct.next.stderr b/tests/ui/traits/normalize/normalize-diverging-alias-in-struct.next.stderr index d7046d2b058ba..d109ed37eb318 100644 --- a/tests/ui/traits/normalize/normalize-diverging-alias-in-struct.next.stderr +++ b/tests/ui/traits/normalize/normalize-diverging-alias-in-struct.next.stderr @@ -4,14 +4,11 @@ error[E0271]: type mismatch resolving `::Diverges normalizes-to LL | field: Box<::Diverges>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ -error[E0271]: type mismatch resolving `::Diverges normalizes-to _` +error: the type `Box<::Diverges>` is not well-formed --> $DIR/normalize-diverging-alias-in-struct.rs:21:12 | LL | field: Box<::Diverges>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ - | -note: required by a bound in `Box` - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/traits/normalize/normalize-diverging-alias-in-struct.rs b/tests/ui/traits/normalize/normalize-diverging-alias-in-struct.rs index 45b2cb56c25f7..7a0738af6874a 100644 --- a/tests/ui/traits/normalize/normalize-diverging-alias-in-struct.rs +++ b/tests/ui/traits/normalize/normalize-diverging-alias-in-struct.rs @@ -21,7 +21,7 @@ struct Foo { field: Box<::Diverges>, //[current]~^ ERROR: overflow evaluating the requirement `::Diverges == _` //[next]~^^ ERROR: type mismatch resolving `::Diverges normalizes-to _` - //[next]~| ERROR: type mismatch resolving `::Diverges normalizes-to _` + //[next]~| ERROR: the type `Box<::Diverges>` is not well-formed } fn main() {} diff --git a/tests/ui/traits/solver-cycles/129541-recursive-struct.rs b/tests/ui/traits/solver-cycles/129541-recursive-struct.rs index bf4b4744dbd4d..c47c7d269f8c4 100644 --- a/tests/ui/traits/solver-cycles/129541-recursive-struct.rs +++ b/tests/ui/traits/solver-cycles/129541-recursive-struct.rs @@ -1,5 +1,4 @@ //~ ERROR reached the recursion limit finding the struct tail for `Hello` -// Regression test for #129541 //@ revisions: unique_curr unique_next multiple_curr multiple_next //@ ignore-compare-mode-next-solver (explicit revisions) diff --git a/tests/ui/wf/return-type-non-wf-no-ice.next.stderr b/tests/ui/wf/return-type-non-wf-no-ice.next.stderr index 888f0893ec7c4..0ee259a401407 100644 --- a/tests/ui/wf/return-type-non-wf-no-ice.next.stderr +++ b/tests/ui/wf/return-type-non-wf-no-ice.next.stderr @@ -1,22 +1,8 @@ -error[E0277]: `T` is not an iterator +error: the type `Foo` is not well-formed --> $DIR/return-type-non-wf-no-ice.rs:13:16 | LL | fn foo() -> Foo { - | ^^^^^^ `T` is not an iterator - | -note: required by a bound in `Foo` - --> $DIR/return-type-non-wf-no-ice.rs:10:8 - | -LL | pub struct Foo(T) - | --- required by a bound in this struct -LL | where -LL | T: Iterator, - | ^^^^^^^^ required by this bound in `Foo` -help: consider restricting type parameter `T` with trait `Iterator` - | -LL | fn foo() -> Foo { - | +++++++++++++++++++++ + | ^^^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/wf/return-type-non-wf-no-ice.rs b/tests/ui/wf/return-type-non-wf-no-ice.rs index 915e33418d7c0..694b8194cdbb9 100644 --- a/tests/ui/wf/return-type-non-wf-no-ice.rs +++ b/tests/ui/wf/return-type-non-wf-no-ice.rs @@ -11,7 +11,8 @@ where ::Item: Default; fn foo() -> Foo { - //~^ ERROR: `T` is not an iterator + //[current]~^ ERROR `T` is not an iterator + //[next]~^^ ERROR: the type `Foo` is not well-formed loop {} }