diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index f1a22fd6af982..ca2e1c80d81bd 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -711,8 +711,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/diagnostics/opaque_types.rs b/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs index 590c2c9c3965b..cddb27af5368f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs +++ b/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs @@ -76,6 +76,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { "non-defining use of `{}` in the defining scope", Ty::new_opaque( infcx.tcx, + ty::IsRigid::No, opaque_type_key.def_id.to_def_id(), opaque_type_key.args ) @@ -220,7 +221,7 @@ impl<'tcx> TypeVisitor> for FindOpaqueRegion<'_, 'tcx> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { // If we find an opaque in a local ty, then for each of its captured regions, // try to find a path between that captured regions and our borrow region... - if let ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) = *ty.kind() + if let ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) = *ty.kind() && let hir::OpaqueTyOrigin::FnReturn { parent, in_trait_or_impl: None } = self.tcx.opaque_ty_origin(def_id) { @@ -277,7 +278,7 @@ impl<'tcx> TypeVisitor> for CheckExplicitRegionMentionAndCollectGen fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { match *ty.kind() { - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => { if self.seen_opaques.insert(def_id) { for (bound, _) in self .tcx diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index e436d95cdb087..96b1366dfb0ff 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -603,7 +603,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let ErrorConstraintInfo { outlived_fr, span, .. } = errci; let mut output_ty = self.regioncx.universal_regions().unnormalized_output_ty; - if let ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }) = *output_ty.kind() { + if let ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }) = *output_ty.kind() { output_ty = self.infcx.tcx.type_of(def_id).instantiate_identity().skip_norm_wip() }; diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 94ad74b67b629..88b893f1add98 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1928,7 +1928,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { | ty::Never | ty::Tuple(_) | ty::UnsafeBinder(_) - | ty::Alias(_) + | ty::Alias(_, _) | ty::Param(_) | ty::Bound(_, _) | ty::Infer(_) @@ -1970,7 +1970,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { | ty::CoroutineWitness(..) | ty::Never | ty::UnsafeBinder(_) - | ty::Alias(_) + | ty::Alias(_, _) | ty::Param(_) | ty::Bound(_, _) | ty::Infer(_) diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs index c057d99c6a41b..db38879ea1d9b 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/member_constraints.rs @@ -176,7 +176,7 @@ impl<'tcx> TypeVisitor> for CollectMemberConstraintsVisitor<'_, '_, | ty::CoroutineClosure(def_id, args) | ty::Coroutine(def_id, args) => self.visit_closure_args(def_id, args), - ty::Alias(ty::AliasTy { kind, args, .. }) + ty::Alias(_, ty::AliasTy { kind, args, .. }) if let Some(variances) = self.cx().opt_alias_variances(kind) => { // Skip lifetime parameters that are not captured, since they do 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 f73719e87c787..446c226eade23 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs @@ -367,7 +367,7 @@ fn compute_definition_site_hidden_types_from_defining_uses<'tcx>( // usage of the opaque type and we can ignore it. This check is mirrored in typeck's // writeback. if !rcx.infcx.tcx.use_typing_mode_post_typeck_until_borrowck() { - if let &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) = + if let &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) = hidden_type.ty.skip_binder().kind() && def_id == opaque_type_key.def_id.to_def_id() && args == opaque_type_key.args @@ -500,7 +500,7 @@ impl<'tcx> FallibleTypeFolder> for ToArgRegionsFolder<'_, 'tcx> { Ty::new_coroutine(tcx, def_id, self.fold_closure_args(def_id, args)?) } - ty::Alias(ty::AliasTy { kind, args, .. }) + ty::Alias(_, ty::AliasTy { kind, args, .. }) if let Some(variances) = tcx.opt_alias_variances(kind) => { let args = tcx.mk_args_from_iter(std::iter::zip(variances, args.iter()).map( @@ -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).to_ty(tcx, ty::IsRigid::No) } _ => ty.try_super_fold_with(self)?, @@ -541,7 +541,7 @@ pub(crate) fn apply_definition_site_hidden_types<'tcx>( for &(key, hidden_type) in opaque_types { let Some(expected) = hidden_types.get(&key.def_id) else { if !tcx.use_typing_mode_post_typeck_until_borrowck() { - if let &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) = + if let &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) = hidden_type.ty.kind() && def_id == key.def_id.to_def_id() && args == key.args diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 450ac46aab521..5281b85b1ed04 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -469,7 +469,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // Necessary for non-trivial patterns whose user-type annotation is an opaque type, // e.g. `let (_a,): Tait = whatever`, see #105897 if !self.infcx.next_trait_solver() - && let ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }) = + && let ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }) = curr_projected_ty.ty.kind() { // There is nothing that we can compare here if we go through an opaque type. @@ -1760,7 +1760,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let tcx = self.tcx(); let maybe_uneval = match constant.const_ { Const::Ty(_, ct) => match ct.kind() { - ty::ConstKind::Unevaluated(uv) => match uv.kind { + ty::ConstKind::Unevaluated(_, uv) => match uv.kind { ty::UnevaluatedConstKind::Projection { def_id } | ty::UnevaluatedConstKind::Inherent { def_id } | ty::UnevaluatedConstKind::Free { def_id } diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index f18884df0b44d..24383eea3600f 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -150,10 +150,10 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { }; let (a, b) = match (a.kind(), b.kind()) { - (&ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }), _) => { + (&ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }), _) => { (a, enable_subtyping(b, true)?) } - (_, &ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. })) => { + (_, &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. })) => { (enable_subtyping(a, false)?, b) } _ => unreachable!( @@ -386,8 +386,8 @@ impl<'b, 'tcx> TypeRelation> for NllTypeRelating<'_, 'b, 'tcx> { } ( - &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id: a_def_id }, .. }), - &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id: b_def_id }, .. }), + &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: a_def_id }, .. }), + &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: b_def_id }, .. }), ) if a_def_id == b_def_id || infcx.next_trait_solver() => { super_combine_tys(&infcx.infcx, self, a, b).map(|_| ()).or_else(|err| { // This behavior is only there for the old solver, the new solver @@ -401,8 +401,8 @@ impl<'b, 'tcx> TypeRelation> for NllTypeRelating<'_, 'b, 'tcx> { if a_def_id.is_local() { self.relate_opaques(a, b) } else { Err(err) } })?; } - (&ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }), _) - | (_, &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. })) + (&ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }), _) + | (_, &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. })) if def_id.is_local() && !self.type_checker.infcx.next_trait_solver() => { self.relate_opaques(a, b)?; diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index b22afca847aa9..69e472b33abac 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(self.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 new file mode 100644 index 0000000000000..dd26ce098e092 --- /dev/null +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -0,0 +1,186 @@ +use std::collections::hash_map::Entry; + +use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext}; +use rustc_codegen_ssa::traits::*; +use rustc_data_structures::fx::FxHashMap; +use rustc_index::bit_set::DenseBitSet; +use rustc_middle::mir::{Body, SourceScope}; +use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv}; +use rustc_middle::ty::{self, Instance}; +use rustc_session::config::DebugInfo; +use rustc_span::{BytePos, DUMMY_SP, hygiene}; + +use super::metadata::file_metadata; +use super::utils::DIB; +use crate::common::CodegenCx; +use crate::llvm; +use crate::llvm::debuginfo::{DILocation, DIScope}; + +/// Produces DIScope DIEs for each MIR Scope which has variables defined in it. +// FIXME(eddyb) almost all of this should be in `rustc_codegen_ssa::mir::debuginfo`. +pub(crate) fn compute_mir_scopes<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + instance: Instance<'tcx>, + mir: &Body<'tcx>, + debug_context: &mut FunctionDebugContext<'tcx, &'ll DIScope, &'ll DILocation>, +) { + // Find all scopes with variables defined in them. + let variables = if cx.sess().opts.debuginfo == DebugInfo::Full { + let mut vars = DenseBitSet::new_empty(mir.source_scopes.len()); + // FIXME(eddyb) take into account that arguments always have debuginfo, + // irrespective of their name (assuming full debuginfo is enabled). + // NOTE(eddyb) actually, on second thought, those are always in the + // function scope, which always exists. + for var_debug_info in &mir.var_debug_info { + vars.insert(var_debug_info.source_info.scope); + } + Some(vars) + } else { + // Nothing to emit, of course. + None + }; + let mut instantiated = DenseBitSet::new_empty(mir.source_scopes.len()); + let mut discriminators = FxHashMap::default(); + // Instantiate all scopes. + for scope in mir.source_scopes.indices() { + make_mir_scope( + cx, + instance, + mir, + &variables, + debug_context, + &mut instantiated, + &mut discriminators, + scope, + ); + } + assert!(instantiated.count() == mir.source_scopes.len()); +} + +fn make_mir_scope<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + instance: Instance<'tcx>, + mir: &Body<'tcx>, + variables: &Option>, + debug_context: &mut FunctionDebugContext<'tcx, &'ll DIScope, &'ll DILocation>, + instantiated: &mut DenseBitSet, + discriminators: &mut FxHashMap, + scope: SourceScope, +) { + if instantiated.contains(scope) { + return; + } + + let scope_data = &mir.source_scopes[scope]; + let parent_scope = if let Some(parent) = scope_data.parent_scope { + make_mir_scope( + cx, + instance, + mir, + variables, + debug_context, + instantiated, + discriminators, + parent, + ); + debug_context.scopes[parent] + } else { + // The root is the function itself. + let file = cx.sess().source_map().lookup_source_file(mir.span.lo()); + debug_context.scopes[scope] = DebugScope { + file_start_pos: file.start_pos, + file_end_pos: file.end_position(), + ..debug_context.scopes[scope] + }; + instantiated.insert(scope); + return; + }; + + if let Some(vars) = variables + && !vars.contains(scope) + && scope_data.inlined.is_none() + { + // Do not create a DIScope if there are no variables defined in this + // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat. + debug_context.scopes[scope] = parent_scope; + instantiated.insert(scope); + return; + } + + let loc = cx.lookup_debug_loc(scope_data.span.lo()); + let file_metadata = file_metadata(cx, &loc.file); + + let dbg_scope = match scope_data.inlined { + Some((callee, _)) => { + // FIXME(eddyb) this would be `self.monomorphize(&callee)` + // if this is moved to `rustc_codegen_ssa::mir::debuginfo`. + let callee = cx.tcx.instantiate_and_normalize_erasing_regions( + instance.args, + cx.typing_env(), + 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()); + cx.dbg_scope_fn(callee, callee_fn_abi, None) + }) + } + None => unsafe { + llvm::LLVMDIBuilderCreateLexicalBlock( + DIB(cx), + parent_scope.dbg_scope, + file_metadata, + loc.line, + loc.col, + ) + }, + }; + + let inlined_at = scope_data.inlined.map(|(_, callsite_span)| { + let callsite_span = hygiene::walk_chain_collapsed(callsite_span, mir.span); + let callsite_scope = parent_scope.adjust_dbg_scope_for_span(cx, callsite_span); + let loc = cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span); + + // NB: In order to produce proper debug info for variables (particularly + // arguments) in multiply-inlined functions, LLVM expects to see a single + // DILocalVariable with multiple different DILocations in the IR. While + // the source information for each DILocation would be identical, their + // inlinedAt attributes will be unique to the particular callsite. + // + // We generate DILocations here based on the callsite's location in the + // source code. A single location in the source code usually can't + // produce multiple distinct calls so this mostly works, until + // macros get involved. A macro can generate multiple calls + // at the same span, which breaks the assumption that we're going to + // produce a unique DILocation for every scope we process here. We + // have to explicitly add discriminators if we see inlines into the + // same source code location. + // + // Note further that we can't key this hashtable on the span itself, + // because these spans could have distinct SyntaxContexts. We have + // to key on exactly what we're giving to LLVM. + match discriminators.entry(callsite_span.lo()) { + Entry::Occupied(mut o) => { + *o.get_mut() += 1; + // NB: We have to emit *something* here or we'll fail LLVM IR verification + // in at least some circumstances (see issue #135322) so if the required + // discriminant cannot be encoded fall back to the dummy location. + unsafe { llvm::LLVMRustDILocationCloneWithBaseDiscriminator(loc, *o.get()) } + .unwrap_or_else(|| { + cx.dbg_loc(callsite_scope, parent_scope.inlined_at, DUMMY_SP) + }) + } + Entry::Vacant(v) => { + v.insert(0); + loc + } + } + }); + + debug_context.scopes[scope] = DebugScope { + dbg_scope, + inlined_at: inlined_at.or(parent_scope.inlined_at), + file_start_pos: loc.file.start_pos, + file_end_pos: loc.file.end_position(), + }; + instantiated.insert(scope); +} diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 039346b1a51db..67c9a85ca408f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -136,7 +136,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), ) } } @@ -219,7 +219,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 32a74d7b70587..0b00b22b1a992 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/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index b7d2051f61741..111ada0241116 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -345,7 +345,7 @@ where Const::Ty(_, ct) => match ct.kind() { ty::ConstKind::Param(_) | ty::ConstKind::Error(_) => None, // Unevaluated consts in MIR bodies don't have associated MIR (e.g. `type const`). - ty::ConstKind::Unevaluated(_) => None, + ty::ConstKind::Unevaluated(_, _) => None, // FIXME(mgca): Investigate whether using `None` for `ConstKind::Value` is overly // strict, and if instead we should be doing some kind of value-based analysis. ty::ConstKind::Value(_) => None, 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 388b6e11f7e5e..3ee11c3f5fbdd 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -97,8 +97,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 7ff9a4a1006a8..855ff1a318ed6 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -362,7 +362,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_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index f1bca03218e07..56c41d7697e0c 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -53,20 +53,21 @@ impl<'tcx> Printer<'tcx> for TypeNamePrinter<'tcx> { // Types with identity (print the module path). ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), args) | ty::FnDef(def_id, args) - | ty::Alias(ty::AliasTy { - kind: ty::Projection { def_id } | ty::Opaque { def_id }, - args, - .. - }) + | ty::Alias( + _, + ty::AliasTy { + kind: ty::Projection { def_id } | ty::Opaque { def_id }, args, .. + }, + ) | ty::Closure(def_id, args) | ty::CoroutineClosure(def_id, args) | ty::Coroutine(def_id, args) => self.print_def_path(def_id, args), ty::Foreign(def_id) => self.print_def_path(def_id, &[]), - ty::Alias(ty::AliasTy { kind: ty::Free { .. }, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Free { .. }, .. }) => { bug!("type_name: unexpected free alias") } - ty::Alias(ty::AliasTy { kind: ty::Inherent { .. }, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Inherent { .. }, .. }) => { bug!("type_name: unexpected inherent projection") } ty::CoroutineWitness(..) => bug!("type_name: unexpected `CoroutineWitness`"), diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs index 3742999d05b5d..20223b66405cd 100644 --- a/compiler/rustc_hir_analysis/src/autoderef.rs +++ b/compiler/rustc_hir_analysis/src/autoderef.rs @@ -165,8 +165,9 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { return None; } - let (normalized_ty, obligations) = self - .normalize_ty(Unnormalized::new(Ty::new_projection(tcx, trait_target_def_id, [ty])))?; + let (normalized_ty, obligations) = self.normalize_ty(Unnormalized::new( + Ty::new_projection(tcx, ty::IsRigid::No, trait_target_def_id, [ty]), + ))?; debug!("overloaded_deref_ty({:?}) = ({:?}, {:?})", ty, normalized_ty, obligations); self.state.obligations.extend(obligations); diff --git a/compiler/rustc_hir_analysis/src/check/always_applicable.rs b/compiler/rustc_hir_analysis/src/check/always_applicable.rs index 7a12b1bf8142a..7a509dcd738ed 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 917360ab8119e..e98307c7c7b18 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -337,7 +337,7 @@ fn check_opaque_meets_bounds<'tcx>( }), }; - let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args); + let opaque_ty = Ty::new_opaque(tcx, ty::IsRigid::No, def_id.to_def_id(), args); // `ReErased` regions appear in the "parent_args" of closures/coroutines. // We're ignoring them here and replacing them with fresh region variables. @@ -534,7 +534,7 @@ fn sanity_check_found_hidden_type<'tcx>( // Nothing was actually constrained. return Ok(()); } - if let &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) = ty.ty.kind() { + if let &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) = ty.ty.kind() { if def_id == key.def_id.to_def_id() && args == key.args { // Nothing was actually constrained, this is an opaque usage that was // only discovered to be opaque after inference vars resolved. @@ -778,7 +778,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), if has_default { // need to store default and type of default let ct = tcx.const_param_default(param.def_id).skip_binder(); - if let ty::ConstKind::Unevaluated(uv) = ct.kind() + if let ty::ConstKind::Unevaluated(_, uv) = ct.kind() && let Some(def_id) = uv.kind.opt_def_id() { tcx.ensure_ok().type_of(def_id); @@ -2191,7 +2191,7 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'_>, opaque_def_id: LocalDefId) -> ErrorG impl<'tcx> ty::TypeVisitor> for OpaqueTypeCollector { fn visit_ty(&mut self, t: Ty<'tcx>) { match *t.kind() { - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id: def }, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: def }, .. }) => { self.opaques.push(def); } ty::Closure(def_id, ..) | ty::Coroutine(def_id, ..) => { @@ -2224,10 +2224,13 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'_>, opaque_def_id: LocalDefId) -> ErrorG let mut label_match = |ty: Ty<'_>, span| { for arg in ty.walk() { if let ty::GenericArgKind::Type(ty) = arg.kind() - && let ty::Alias(ty::AliasTy { - kind: ty::Opaque { def_id: captured_def_id }, - .. - }) = *ty.kind() + && let ty::Alias( + _, + ty::AliasTy { + kind: ty::Opaque { def_id: captured_def_id }, + .. + }, + ) = *ty.kind() && captured_def_id == opaque_def_id.to_def_id() { err.span_label( 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 b3d1f2a1489a5..ce4c21ff8d86e 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", + ), + ), ); } } @@ -826,7 +829,7 @@ where } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if let &ty::Alias(ty::AliasTy { kind: ty::Projection { def_id }, args: proj_args, .. }) = + if let &ty::Alias(_, ty::AliasTy { kind: ty::Projection { def_id }, args: proj_args, .. }) = ty.kind() && self.cx().is_impl_trait_in_trait(def_id) { @@ -930,10 +933,10 @@ impl<'tcx> ty::FallibleTypeFolder> for RemapHiddenTyRegions<'tcx> { } else { let guar = match region.opt_param_def_id(self.tcx, self.impl_m_def_id) { Some(def_id) => { - let return_span = if let &ty::Alias(ty::AliasTy { - kind: ty::Opaque { def_id: opaque_ty_def_id }, - .. - }) = self.ty.kind() + let return_span = if let &ty::Alias( + _, + ty::AliasTy { kind: ty::Opaque { def_id: opaque_ty_def_id }, .. }, + ) = self.ty.kind() { self.tcx.def_span(opaque_ty_def_id) } else { @@ -2721,7 +2724,7 @@ fn param_env_with_gat_bounds<'tcx>( let bound_vars = tcx.mk_bound_variable_kinds(&bound_vars); match normalize_impl_ty.kind() { - &ty::Alias(ty::AliasTy { kind: ty::Projection { def_id }, args, .. }) + &ty::Alias(_, ty::AliasTy { kind: ty::Projection { def_id }, args, .. }) if def_id == trait_ty.def_id && args == rebased_args => { // Don't include this predicate if the projected type is @@ -2764,7 +2767,7 @@ fn try_report_async_mismatch<'tcx>( return Ok(()); } - let ty::Alias(ty::AliasTy { kind: ty::Projection { def_id: async_future_def_id }, .. }) = + let ty::Alias(_, ty::AliasTy { kind: ty::Projection { def_id: async_future_def_id }, .. }) = *tcx.fn_sig(trait_m.def_id).skip_binder().skip_binder().output().kind() else { bug!("expected `async fn` to return an RPITIT"); diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index 1ef1b39d4aab1..b84c864a80f5f 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -89,6 +89,7 @@ pub(crate) fn check_refining_return_position_impl_trait_in_trait<'tcx>( // If the hidden type is not an opaque, then we have "refined" the trait signature. let ty::Alias( + _, impl_opaque @ ty::AliasTy { kind: ty::Opaque { def_id: impl_opaque_def_id }, .. }, ) = *hidden_ty.kind() else { @@ -267,7 +268,7 @@ struct ImplTraitInTraitCollector<'tcx> { impl<'tcx> TypeVisitor> for ImplTraitInTraitCollector<'tcx> { fn visit_ty(&mut self, ty: Ty<'tcx>) { - if let ty::Alias(proj @ ty::AliasTy { kind: ty::Projection { def_id }, .. }) = *ty.kind() + if let ty::Alias(_, proj @ ty::AliasTy { kind: ty::Projection { def_id }, .. }) = *ty.kind() && self.tcx.is_impl_trait_in_trait(def_id) { if self.types.insert(proj) { @@ -317,9 +318,10 @@ fn report_mismatched_rpitit_signature<'tcx>( let mut return_ty = trait_m_sig.output().fold_with(&mut super::RemapLateParam { tcx, mapping }); if tcx.asyncness(impl_m_def_id).is_async() && tcx.asyncness(trait_m_def_id).is_async() { - let &ty::Alias(ty::AliasTy { - kind: ty::Projection { def_id: future_ty_def_id }, args, .. - }) = return_ty.kind() + let &ty::Alias( + _, + ty::AliasTy { kind: ty::Projection { def_id: future_ty_def_id }, args, .. }, + ) = return_ty.kind() else { span_bug!( tcx.def_span(trait_m_def_id), diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 09a3cf4d182f8..9dd7bb8058afc 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -631,6 +631,7 @@ pub(crate) fn check_intrinsic_type( vec![Ty::new_imm_ref(tcx, ty::Region::new_bound(tcx, ty::INNERMOST, br), param(0))], Ty::new_projection_from_args( tcx, + ty::IsRigid::No, discriminant_def_id, tcx.mk_args(&[param(0).into()]), ), diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 0b57b4e259a85..bc86cc5905d84 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -487,7 +487,7 @@ fn fn_sig_suggestion<'tcx>( let mut output = sig.output(); let asyncness = if tcx.asyncness(assoc.def_id).is_async() { - output = if let ty::Alias(alias_ty) = *output.kind() + output = if let ty::Alias(_, alias_ty) = *output.kind() && let Some(output) = tcx .explicit_item_self_bounds(alias_ty.kind.def_id()) .iter_instantiated_copied(tcx, alias_ty.args) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 51c345a455f90..bf8593eb61882 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -782,7 +782,7 @@ impl<'tcx> GATArgsCollector<'tcx> { impl<'tcx> TypeVisitor> for GATArgsCollector<'tcx> { fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { - &ty::Alias(ty::AliasTy { kind: ty::Projection { def_id }, args, .. }) + &ty::Alias(_, ty::AliasTy { kind: ty::Projection { def_id }, args, .. }) if def_id == self.gat => { for (idx, arg) in args.iter().enumerate() { @@ -1509,7 +1509,7 @@ pub(super) fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, def_id: | ty::ConstKind::Bound(_, _) => unreachable!(), ty::ConstKind::Error(_) | ty::ConstKind::Expr(_) => continue, ty::ConstKind::Value(cv) => cv.ty, - ty::ConstKind::Unevaluated(uv) => uv.type_of(infcx.tcx).skip_norm_wip(), + ty::ConstKind::Unevaluated(_, uv) => uv.type_of(infcx.tcx).skip_norm_wip(), ty::ConstKind::Param(param_ct) => { param_ct.find_const_ty_from_env(wfcx.param_env) } @@ -1585,7 +1585,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/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index d154503f4ec04..4e3aa41942845 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -203,10 +203,13 @@ impl<'tcx> InherentCollect<'tcx> { | ty::FnPtr(..) | ty::Tuple(..) | ty::UnsafeBinder(_) => self.check_primitive_impl(id, self_ty), - ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Opaque { .. }, - .. - }) + ty::Alias( + _, + ty::AliasTy { + kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Opaque { .. }, + .. + }, + ) | ty::Param(_) => { Err(self.tcx.dcx().emit_err(diagnostics::InherentNominal { span: item_span })) } @@ -215,7 +218,7 @@ impl<'tcx> InherentCollect<'tcx> { | ty::CoroutineClosure(..) | ty::Coroutine(..) | ty::CoroutineWitness(..) - | ty::Alias(ty::AliasTy { kind: ty::Free { .. }, .. }) + | ty::Alias(_, ty::AliasTy { kind: ty::Free { .. }, .. }) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) => { diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index d49326a089c90..c3bd09f2a4767 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -194,7 +194,7 @@ pub(crate) fn orphan_check_impl( NonlocalImpl::DisallowOther, ), - ty::Alias(ty::AliasTy { kind, .. }) => { + ty::Alias(_, ty::AliasTy { kind, .. }) => { let problematic_kind = match kind { // trait Id { type This: ?Sized; } // impl Id for T { @@ -440,7 +440,7 @@ fn emit_orphan_check_error<'tcx>( }); } } - ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }) => { diag.subdiagnostic(diagnostics::OnlyCurrentTraitsOpaque { span }); } ty::RawPtr(ptr_ty, mutbl) => { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index c8f6e5da69b56..275fed00a4f8a 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1085,7 +1085,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>( @@ -1363,7 +1363,12 @@ pub fn suggest_impl_trait<'tcx>( let item_ty = ocx.normalize( &ObligationCause::dummy(), param_env, - Unnormalized::new(Ty::new_projection_from_args(infcx.tcx, assoc_item_def_id, args)), + Unnormalized::new(Ty::new_projection_from_args( + infcx.tcx, + ty::IsRigid::No, + assoc_item_def_id, + args, + )), ); // FIXME(compiler-errors): We may benefit from resolving regions here. if ocx.try_evaluate_obligations().is_empty() @@ -1405,7 +1410,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, @@ -1626,7 +1631,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 { @@ -1676,7 +1681,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); @@ -1688,8 +1693,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..46007503539ca 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -33,6 +33,7 @@ fn associated_type_bounds<'tcx>( ty::print::with_reduced_queries!({ let item_ty = Ty::new_projection_from_args( tcx, + ty::IsRigid::No, assoc_item_def_id.to_def_id(), GenericArgs::identity_for_item(tcx, assoc_item_def_id), ); @@ -144,6 +145,7 @@ fn remap_gat_vars_and_recurse_into_nested_projections<'tcx>( let gat_vars = loop { if let ty::Alias( + _, alias_ty @ ty::AliasTy { kind: ty::Projection { def_id: alias_ty_def_id }, .. }, ) = *clause_ty.kind() { @@ -430,7 +432,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_iter(bounds); } Some(ty::ImplTraitInTraitData::Impl { .. }) => { span_bug!(tcx.def_span(def_id), "RPITIT in impl should not have item bounds") @@ -457,7 +459,7 @@ pub(super) fn explicit_item_bounds_with_filter( in_trait_or_impl: Some(hir::RpitContext::Trait), } => { let args = GenericArgs::identity_for_item(tcx, def_id); - let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args); + let item_ty = Ty::new_opaque(tcx, ty::IsRigid::No, def_id.to_def_id(), args); let bounds = &*tcx.arena.alloc_slice( &opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter) .to_vec() @@ -476,7 +478,7 @@ pub(super) fn explicit_item_bounds_with_filter( } | rustc_hir::OpaqueTyOrigin::TyAlias { parent: _, .. } => { let args = GenericArgs::identity_for_item(tcx, def_id); - let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args); + let item_ty = Ty::new_opaque(tcx, ty::IsRigid::No, def_id.to_def_id(), args); let bounds = opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter); assert_only_contains_predicates_from(filter, bounds, item_ty); bounds @@ -486,7 +488,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_iter(bounds) } pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> ty::EarlyBinder<'_, ty::Clauses<'_>> { @@ -515,9 +517,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()), + ) } } @@ -549,11 +554,10 @@ impl<'tcx> TypeFolder> for AssocTyToOpaque<'tcx> { } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if let &ty::Alias(ty::AliasTy { - kind: ty::Projection { def_id: projection_ty_def_id }, - args, - .. - }) = ty.kind() + if let &ty::Alias( + _, + ty::AliasTy { kind: ty::Projection { def_id: projection_ty_def_id }, args, .. }, + ) = ty.kind() && let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) = self.tcx.opt_rpitit_info(projection_ty_def_id) && fn_def_id == self.fn_def_id diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index db22b57ad22a6..e1798c24838d1 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -433,7 +433,7 @@ fn const_evaluatable_predicates_of<'tcx>( impl<'tcx> TypeVisitor> for ConstCollector<'tcx> { fn visit_const(&mut self, c: ty::Const<'tcx>) { - if let ty::ConstKind::Unevaluated(uv) = c.kind() { + if let ty::ConstKind::Unevaluated(_, uv) = c.kind() { if is_const_param_default(self.tcx, uv.kind) { // Do not look into const param defaults, // these get checked when they are actually instantiated. @@ -519,11 +519,10 @@ pub(super) fn explicit_predicates_of<'tcx>( // identity args of the trait. // * It must be an associated type for this trait (*not* a // supertrait). - if let &ty::Alias(ty::AliasTy { - kind: ty::Projection { def_id: projection_def_id }, - args, - .. - }) = ty.kind() + if let &ty::Alias( + _, + ty::AliasTy { kind: ty::Projection { def_id: projection_def_id }, args, .. }, + ) = ty.kind() { args == trait_identity_args // FIXME(return_type_notation): This check should be more robust @@ -745,7 +744,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_iter(implied_bounds) } // Make sure when elaborating supertraits, probing for associated types, etc., @@ -919,7 +918,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_iter(&[] as &[_]) }; let mut extend = None; @@ -967,7 +966,7 @@ pub(super) fn type_param_predicates<'tcx>( self_ty, ); - ty::EarlyBinder::bind(bounds) + ty::EarlyBinder::bind_iter(bounds) } impl<'tcx> ItemCtxt<'tcx> { diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 70129192faa2c..3c7cc160a4b3d 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -2574,10 +2574,10 @@ fn is_late_bound_map( ty::Param(param_ty) => { self.arg_is_constrained[param_ty.index as usize] = true; } - ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. }, - .. - }) => return, + ty::Alias( + _, + ty::AliasTy { kind: ty::Projection { .. } | ty::Inherent { .. }, .. }, + ) => return, _ => (), } t.super_visit_with(self) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index d729a4adacec2..9c8e61d89da97 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -33,21 +33,28 @@ 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, + ty::IsRigid::No, + opaque_def_id, + ty::GenericArgs::identity_for_item(tcx, opaque_def_id), + ), + ); } None => {} } @@ -240,9 +247,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 aae06aedc7b7a..88936b375a12f 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/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs index efd3cb2acb422..46b2eb538f080 100644 --- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs +++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs @@ -63,14 +63,17 @@ impl<'tcx> TypeVisitor> for ParameterCollector { fn visit_ty(&mut self, t: Ty<'tcx>) { match *t.kind() { // Projections are not injective in general. - ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Opaque { .. }, - .. - }) if !self.include_nonconstraining => { + ty::Alias( + _, + ty::AliasTy { + kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Opaque { .. }, + .. + }, + ) if !self.include_nonconstraining => { return; } // All free alias types should've been expanded beforehand. - ty::Alias(ty::AliasTy { kind: ty::Free { .. }, .. }) + ty::Alias(_, ty::AliasTy { kind: ty::Free { .. }, .. }) if !self.include_nonconstraining => { bug!("unexpected free alias type") diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index 7f3edd7f09231..1da27a3a1bc21 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -516,7 +516,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, )); } @@ -616,7 +618,7 @@ pub(crate) fn inherit_sig_for_delegation_item<'tcx>( let (parent_args, child_args) = tcx.delegation_user_specified_args(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 9d6c647329aa0..18492e09e92be 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -590,7 +590,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .map_bound(|projection_term| projection_term.expect_ty()); // Calling `skip_binder` is okay, because `lower_bounds` expects the `param_ty` // parameter to have a skipped binder. - let param_ty = Ty::new_alias(tcx, projection_ty.skip_binder()); + let param_ty = + Ty::new_alias(tcx, ty::IsRigid::No, projection_ty.skip_binder()); self.lower_bounds( param_ty, hir_bounds, @@ -680,7 +681,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::Binder::bind_with_vars(trait_ref, tcx.late_bound_vars(item_segment.hir_id)); match self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span) { - Ok(ty) => Ty::new_alias(tcx, ty), + Ok(ty) => Ty::new_alias(tcx, ty::IsRigid::No, ty), Err(guar) => Ty::new_error(tcx, guar), } } @@ -728,7 +729,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } match self.lower_return_type_notation_ty(bound, item_def_id, hir_ty.span) { - Ok(ty) => Ty::new_alias(tcx, ty), + Ok(ty) => Ty::new_alias(tcx, ty::IsRigid::No, ty), Err(guar) => Ty::new_error(tcx, guar), } } @@ -792,7 +793,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Next, we need to check that the return-type notation is being used on // an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait). let output = tcx.fn_sig(item_def_id).skip_binder().output(); - let output = if let ty::Alias(alias_ty) = *output.skip_binder().kind() + let output = if let ty::Alias(_, alias_ty) = *output.skip_binder().kind() && let ty::AliasTy { kind: ty::Projection { def_id: projection_def_id }, .. } = alias_ty && tcx.is_impl_trait_in_trait(projection_def_id) { @@ -811,7 +812,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 7909fdbf2365e..4e550dc52987f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1216,7 +1216,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // 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); - Ty::new_alias(tcx, alias_ty) + Ty::new_alias(tcx, ty::IsRigid::No, alias_ty) } else { tcx.at(span).type_of(def_id).instantiate(tcx, args).skip_norm_wip() } @@ -1357,7 +1357,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { TypeRelativePath::AssocItem(alias_term) => { let alias_ty = alias_term.expect_ty(); let def_id = alias_ty.kind.def_id(); - let ty = alias_ty.to_ty(tcx); + let ty = alias_ty.to_ty(tcx, ty::IsRigid::No); let ty = self.check_param_uses_if_mcg(ty, span, false); Ok((ty, tcx.def_kind(def_id), def_id)) } @@ -1396,7 +1396,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if let Some(def_id) = alias_ct.kind.opt_def_id() { self.require_type_const_attribute(def_id, span)?; } - let ct = Const::new_unevaluated(tcx, alias_ct); + let ct = Const::new_unevaluated(tcx, ty::IsRigid::No, alias_ct); let ct = self.check_param_uses_if_mcg(ct, span, false); Ok(ct) } @@ -1833,7 +1833,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::AssocTag::Type, ) { Ok((item_def_id, item_args)) => { - Ty::new_projection_from_args(self.tcx(), item_def_id, item_args) + Ty::new_projection_from_args(self.tcx(), ty::IsRigid::No, item_def_id, item_args) } Err(guar) => Ty::new_error(self.tcx(), guar), } @@ -1864,7 +1864,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::UnevaluatedConstKind::new_from_def_id(tcx, item_def_id), item_args, ); - Ok(Const::new_unevaluated(tcx, uv)) + Ok(Const::new_unevaluated(tcx, ty::IsRigid::No, uv)) } /// Lower a [resolved][hir::QPath::Resolved] (type-level) associated item path. @@ -2118,7 +2118,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { GenericsArgsErrExtend::OpaqueTy, ); let args = self.lower_generic_args_of_path_segment(span, did, segment); - Ty::new_opaque(tcx, did, args) + Ty::new_opaque(tcx, ty::IsRigid::No, did, args) } Res::Def( DefKind::Enum @@ -2317,7 +2317,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 @@ -2328,7 +2331,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 @@ -2338,11 +2344,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; @@ -2708,6 +2717,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let args = self.lower_generic_args_of_path_segment(span, did, segment); ty::Const::new_unevaluated( tcx, + ty::IsRigid::No, ty::UnevaluatedConst::new( tcx, ty::UnevaluatedConstKind::new_from_def_id(tcx, did), @@ -2865,6 +2875,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Some(v) => v, None => ty::Const::new_unevaluated( tcx, + ty::IsRigid::No, ty::UnevaluatedConst::new( tcx, ty::UnevaluatedConstKind::Anon { def_id: anon.def_id.to_def_id() }, @@ -3475,9 +3486,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { debug!(?args); if in_trait.is_some() { - Ty::new_projection_from_args(tcx, def_id, args) + Ty::new_projection_from_args(tcx, ty::IsRigid::No, def_id, args) } else { - Ty::new_opaque(tcx, def_id, args) + Ty::new_opaque(tcx, ty::IsRigid::No, def_id, args) } } diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs index d3a57a4d8e5d3..97ef6a2461495 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_iter(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 174f702dcd0c4..b2deea63dfd16 100644 --- a/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs +++ b/compiler/rustc_hir_analysis/src/outlives/implicit_infer.rs @@ -81,8 +81,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_iter(item_required_predicates), + ); } } @@ -154,7 +156,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( ); } - ty::Alias(ty::AliasTy { kind: ty::Free { def_id }, args, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Free { def_id }, args, .. }) => { // This corresponds to a type like `Type<'a, T>`. // We check inferred and explicit predicates. debug!("Free"); @@ -204,7 +206,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( } } - ty::Alias(ty::AliasTy { kind: ty::Projection { def_id }, args, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Projection { def_id }, args, .. }) => { // This corresponds to a type like `<() as Trait<'a, T>>::Type`. // We only use the explicit predicates of the trait but // not the ones of the associated type itself. @@ -220,7 +222,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( } // FIXME(inherent_associated_types): Use the explicit predicates from the parent impl. - ty::Alias(ty::AliasTy { kind: ty::Inherent { .. }, .. }) => {} + ty::Alias(_, ty::AliasTy { kind: ty::Inherent { .. }, .. }) => {} _ => {} } diff --git a/compiler/rustc_hir_analysis/src/outlives/utils.rs b/compiler/rustc_hir_analysis/src/outlives/utils.rs index 99a633e2b7d1f..ac58a37cc8e81 100644 --- a/compiler/rustc_hir_analysis/src/outlives/utils.rs +++ b/compiler/rustc_hir_analysis/src/outlives/utils.rs @@ -102,7 +102,7 @@ pub(crate) fn insert_outlives_predicate<'tcx>( // // Here we want to add an explicit `where ::Item: 'a` // or `Opaque: 'a` depending on the alias kind. - let ty = alias_ty.to_ty(tcx); + let ty = alias_ty.to_ty(tcx, ty::IsRigid::No); required_predicates .entry(ty::OutlivesPredicate(ty.into(), outlived_region)) .or_insert(span); diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index 3e7f5b73e4569..095213322a9fd 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -260,15 +260,18 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_args(current, def.did(), args, variance); } - ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Opaque { .. }, - args, - .. - }) => { + ty::Alias( + _, + ty::AliasTy { + kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Opaque { .. }, + args, + .. + }, + ) => { self.add_constraints_from_invariant_args(current, args, variance); } - ty::Alias(ty::AliasTy { kind: ty::Free { .. }, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Free { .. }, .. }) => { let ty = self.tcx().expand_free_alias_tys(ty); self.add_constraints_from_ty(current, ty, variance); } @@ -405,7 +408,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { debug!("add_constraints_from_const(c={:?}, variance={:?})", c, variance); match &c.kind() { - ty::ConstKind::Unevaluated(uv) => { + ty::ConstKind::Unevaluated(_, uv) => { self.add_constraints_from_invariant_args(current, uv.args, variance); } _ => {} diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index c4287a8d0bb10..5c42d79621524 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -139,7 +139,7 @@ fn variance_of_opaque( #[instrument(level = "trace", skip(self), ret)] fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => { self.visit_opaque(*def_id, args); } _ => t.super_visit_with(self), diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index e043e1afaf61f..3f3373d372ddd 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -245,7 +245,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.may_coerce(arm_ty, ret_ty) && prior_arm.is_none_or(|(_, ty, _)| self.may_coerce(ty, ret_ty)) // The match arms need to unify for the case of `impl Trait`. - && !matches!(ret_ty.kind(), ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. })) + && !matches!(ret_ty.kind(), ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. })) } _ => false, }; @@ -532,7 +532,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let expected_ty = expectation.to_option(self)?; let (def_id, args) = match *expected_ty.kind() { // FIXME: Could also check that the RPIT is not defined - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => { (def_id.as_local()?, args) } // FIXME(-Znext-solver=no): Remove this branch once `replace_opaque_types_with_infer` is gone. diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index c8680be6de718..d1e64dc4f8f40 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -123,7 +123,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Pointers to foreign types are thin, despite being unsized ty::Foreign(..) => Some(PointerKind::Thin), // We should really try to normalize here. - ty::Alias(pi) => Some(PointerKind::OfAlias(pi)), + ty::Alias(_, pi) => Some(PointerKind::OfAlias(pi)), ty::Param(p) => Some(PointerKind::OfParam(p)), // Insufficient type information. ty::Placeholder(..) | ty::Bound(..) | ty::Infer(_) => None, diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 570d33aaf20e0..41aebea1c7ebe 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -294,7 +294,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { closure_kind: hir::ClosureKind, ) -> (Option>, Option) { match *expected_ty.kind() { - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => self + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => self .deduce_closure_signature_from_predicates( expected_ty, closure_kind, @@ -990,14 +990,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { get_future_output(obligation.predicate, obligation.cause.span) })? } - ty::Alias(ty::AliasTy { kind: ty::Projection { .. }, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Projection { .. }, .. }) => { return Some(Ty::new_error_with_message( self.tcx, closure_span, "this projection should have been projected to an opaque type", )); } - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => self + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => self .tcx .explicit_item_self_bounds(def_id) .iter_instantiated_copied(self.tcx, args) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 4465bbc34a562..2cf95c9474b01 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2976,7 +2976,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(ident.span, "unknown field"); self.point_at_param_definition(&mut err, param_ty); } - ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }) => { self.suggest_await_on_field_access(&mut err, ident, base, base_ty.peel_refs()); } _ => { @@ -3578,6 +3578,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.param_env, Unnormalized::new(Ty::new_projection_from_args( self.tcx, + ty::IsRigid::No, index_trait_output_def_id, impl_trait_ref.args, )), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index 825aa37065e15..1bc0270e9f3ab 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -1058,9 +1058,10 @@ fn find_param_in_ty<'tcx>( return true; } if let ty::GenericArgKind::Type(ty) = arg.kind() - && let ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. }, .. - }) = ty.kind() + && let ty::Alias( + _, + ty::AliasTy { kind: ty::Projection { .. } | ty::Inherent { .. }, .. }, + ) = ty.kind() { // This logic may seem a bit strange, but typically when // we have a projection type in a function signature, the diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index a295cc4127b67..890110e431fa2 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -161,7 +161,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::ConstKind::Param(_) | ty::ConstKind::Expr(_) | ty::ConstKind::Placeholder(_) - | ty::ConstKind::Unevaluated(_) => enforce_copy_bound(element, element_ty), + | ty::ConstKind::Unevaluated(_, _) => enforce_copy_bound(element, element_ty), ty::ConstKind::Bound(_, _) | ty::ConstKind::Infer(_) | ty::ConstKind::Error(_) => { unreachable!() @@ -1396,7 +1396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id: new_def_id }, .. }) + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: new_def_id }, .. }) | ty::Closure(new_def_id, _) | ty::FnDef(new_def_id, _) => { def_id = new_def_id; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 922a9d7e95bda..c4a1b56320ff1 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -294,7 +294,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_iter(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) => { @@ -399,10 +399,13 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { match ty.kind() { ty::Adt(adt_def, _) => Some(*adt_def), // FIXME(#104767): Should we handle bound regions here? - ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }, - .. - }) if !ty.has_escaping_bound_vars() => { + ty::Alias( + _, + ty::AliasTy { + kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }, + .. + }, + ) if !ty.has_escaping_bound_vars() => { self.normalize(span, Unnormalized::new_wip(ty)).ty_adt_def() } _ => None, @@ -416,11 +419,10 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { // WF obligations that are registered elsewhere, but they have a // better cause code assigned to them in `add_required_obligations_for_hir`. // This means that they should shadow obligations with worse spans. - if let ty::Alias(ty::AliasTy { - kind: ty::Projection { def_id } | ty::Free { def_id }, - args, - .. - }) = ty.kind() + if let ty::Alias( + _, + ty::AliasTy { kind: ty::Projection { def_id } | ty::Free { def_id }, args, .. }, + ) = ty.kind() { self.add_required_obligations_for_hir(span, *def_id, args, hir_id); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 24e2b030cdc72..e0cf6effeaba7 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -294,7 +294,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return false; }; - let item_type = Ty::new_projection(tcx, iterator_item_id, [found]); + let item_type = Ty::new_projection(tcx, ty::IsRigid::No, iterator_item_id, [found]); let item_type = self.normalize(expr.span, rustc_middle::ty::Unnormalized::new_wip(item_type)); diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 4258896deec70..e8921841c4405 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -2050,7 +2050,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // HACK: opaque types will match anything for which their bounds hold. // Thus we need to prevent them from trying to match the `&_` autoref // candidates that get created for `&self` trait methods. - &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }) + &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }) if !self.next_trait_solver() && self.infcx.can_define_opaque_ty(def_id) && !xform_self_ty.is_ty_var() => diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 8c9f764c0bded..04a67fbc587ba 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -178,7 +178,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ty::Slice(..) | ty::Adt(..) - | ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }) => { + | ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }) => { for unsatisfied in unsatisfied_predicates.iter() { if is_iterator_predicate(unsatisfied.0) { return true; @@ -3755,10 +3755,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ty::Float(_) | ty::Adt(_, _) | ty::Str - | ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. }, - .. - }) + | ty::Alias( + _, + ty::AliasTy { + kind: ty::Projection { .. } | ty::Inherent { .. }, .. + }, + ) | ty::Param(_) => format!("{deref_ty}"), // we need to test something like <&[_]>::len or <(&[u32])>::len // and Vec::function(); diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 9e0ca938a438d..ad9d0df78b333 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -2745,6 +2745,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The expected type for the deref pat's inner pattern is `::Target`. let target_ty = Ty::new_projection( tcx, + ty::IsRigid::No, tcx.require_lang_item(hir::LangItem::DerefTarget, span), [source_ty], ); diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index ba5b55b43049f..9e242c630d767 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -567,7 +567,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { for (opaque_type_key, hidden_type) in opaque_types { let hidden_type = self.resolve(hidden_type, &hidden_type.span); let opaque_type_key = self.resolve(opaque_type_key, &hidden_type.span); - if let &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) = + if let &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) = hidden_type.ty.kind() && def_id == opaque_type_key.def_id.to_def_id() && args == opaque_type_key.args @@ -1055,7 +1055,7 @@ impl<'tcx> TypeVisitor> for HasRecursiveOpaque<'_, 'tcx> { type Result = ControlFlow<()>; fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result { - if let ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) = *t.kind() + if let ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) = *t.kind() && let Some(def_id) = def_id.as_local() { if self.def_id == def_id { diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 5641523c304c9..733cf757a17cb 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -519,7 +519,7 @@ impl<'tcx> InferCtxt<'tcx> { self.at(cause, param_env) .eq( DefineOpaqueTypes::Yes, - Ty::new_opaque(self.tcx, a.def_id.to_def_id(), a.args), + Ty::new_opaque(self.tcx, ty::IsRigid::No, a.def_id.to_def_id(), a.args), b, )? .obligations, diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index c23bc4adf914c..10f58bfbb6560 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 0d93e1478c420..e0ac71f22225d 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1245,10 +1245,11 @@ impl<'tcx> InferCtxt<'tcx> { .unwrap_or(ct), InferConst::Fresh(_) => ct, }, + ty::ConstKind::Param(_) | ty::ConstKind::Bound(_, _) | ty::ConstKind::Placeholder(_) - | ty::ConstKind::Unevaluated(_) + | ty::ConstKind::Unevaluated(_, _) | ty::ConstKind::Value(_) | ty::ConstKind::Error(_) | ty::ConstKind::Expr(_) => ct, diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index c5c58ae1a29b4..dcd53aaf4f11c 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -45,7 +45,7 @@ impl<'tcx> InferCtxt<'tcx> { lt_op: |lt| lt, ct_op: |ct| ct, ty_op: |ty| match *ty.kind() { - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }) + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }) if self.can_define_opaque_ty(def_id) && !ty.has_escaping_bound_vars() => { let def_span = self.tcx.def_span(def_id); @@ -85,7 +85,7 @@ impl<'tcx> InferCtxt<'tcx> { ) -> Result>>, TypeError<'tcx>> { debug_assert!(!self.next_trait_solver()); let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() { - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) if def_id.is_local() => { let def_id = def_id.expect_local(); @@ -136,7 +136,7 @@ impl<'tcx> InferCtxt<'tcx> { return None; } - if let ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id: b_def_id }, .. }) = + if let ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: b_def_id }, .. }) = *b.kind() { // We could accept this, but there are various ways to handle this situation, @@ -324,6 +324,7 @@ impl<'tcx> InferCtxt<'tcx> { // FIXME(RPITIT): Don't replace RPITITs with inference vars. // FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too. ty::Alias( + _, projection_ty @ ty::AliasTy { kind: ty::Projection { def_id }, .. }, ) if !projection_ty.has_escaping_bound_vars() && !tcx.is_impl_trait_in_trait(def_id) @@ -344,11 +345,10 @@ impl<'tcx> InferCtxt<'tcx> { } // Replace all other mentions of the same opaque type with the hidden type, // as the bounds must hold on the hidden type after all. - ty::Alias(ty::AliasTy { - kind: ty::Opaque { def_id: def_id2 }, - args: args2, - .. - }) if def_id == def_id2 && args == args2 => hidden_ty, + ty::Alias( + _, + ty::AliasTy { kind: ty::Opaque { def_id: def_id2 }, args: args2, .. }, + ) if def_id == def_id2 && args == args2 => hidden_ty, _ => ty, }, lt_op: |lt| lt, diff --git a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs index b4594bd60f3ba..7e7e50f92055a 100644 --- a/compiler/rustc_infer/src/infer/outlives/for_liveness.rs +++ b/compiler/rustc_infer/src/infer/outlives/for_liveness.rs @@ -56,7 +56,7 @@ where // either `'static` or a unique outlives region, and if one is // found, we just need to prove that that region is still live. // If one is not found, then we continue to walk through the alias. - ty::Alias(ty::AliasTy { kind, args, .. }) => { + ty::Alias(_is_rigid, alias_ty @ ty::AliasTy { kind, args, .. }) => { let tcx = self.tcx; let param_env = self.param_env; let outlives_bounds: Vec<_> = tcx @@ -76,7 +76,13 @@ where &outlives.map_bound(|ty::OutlivesPredicate(ty, bound)| { VerifyIfEq { ty, bound } }), - ty, + // FIXME(rigid_aliases_marker): We have alias relating in + // `extract_verify_if_eq` which checks rigidness equality. + // Types coming out of `item_bounds` are marked as non-rigid + // while the visited ty can be rigid. We only set the outer + // alias to non-rigid since the instantiation args can contain + // rigid aliases. + alias_ty.to_ty(tcx, ty::IsRigid::No), ) } }) diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs index 479daf67a8ba3..1b4f8dd46d9c8 100644 --- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs +++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs @@ -80,6 +80,10 @@ pub(super) fn can_match_erased_ty<'tcx>( assert!(!outlives_predicate.has_escaping_bound_vars()); let erased_outlives_predicate = tcx.erase_and_anonymize_regions(outlives_predicate); let outlives_ty = erased_outlives_predicate.skip_binder().0; + // FIXME(rigid_aliases_marker): The aliases in `erased_ty` are currently not + // marked as rigid. We should probably do that instead as we only ever want to + // prove `TypeOutlives` once all aliases in them have been normalized. + let outlives_ty = ty::set_aliases_to_non_rigid(tcx, outlives_ty).skip_normalization(); if outlives_ty == erased_ty { // pointless micro-optimization true diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs index 8484b7c222955..7bf2d7c34a496 100644 --- a/compiler/rustc_infer/src/infer/outlives/verify.rs +++ b/compiler/rustc_infer/src/infer/outlives/verify.rs @@ -96,7 +96,10 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { &self, alias_ty: ty::AliasTy<'tcx>, ) -> Vec> { - let erased_alias_ty = self.tcx.erase_and_anonymize_regions(alias_ty.to_ty(self.tcx)); + // FIXME(rigid_aliases_marker): This should use `IsRigid::Yes` once the old solver + // is gone. + let erased_alias_ty = + self.tcx.erase_and_anonymize_regions(alias_ty.to_ty(self.tcx, ty::IsRigid::No)); self.declared_generic_bounds_from_env_for_erased_ty(erased_alias_ty) } @@ -104,8 +107,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { pub(crate) fn alias_bound(&self, alias_ty: ty::AliasTy<'tcx>) -> VerifyBound<'tcx> { // Search the env for where clauses like `P: 'a`. let env_bounds = self.approx_declared_bounds_from_env(alias_ty).into_iter().map(|binder| { + // FIXME(rigid_aliases_marker): We probably want to assert the alias is rigid here. if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars() - && let ty::Alias(alias_ty_from_bound) = *ty.kind() + && let ty::Alias(_is_rigid, alias_ty_from_bound) = *ty.kind() && alias_ty_from_bound == alias_ty { // Micro-optimize if this is an exact match (this @@ -236,8 +240,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // And therefore we can safely use structural equality for alias types. (GenericKind::Param(p1), ty::Param(p2)) if p1 == p2 => {} (GenericKind::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => {} - (GenericKind::Alias(a1), ty::Alias(a2)) if a1.kind.def_id() == a2.kind.def_id() => { - } + // FIXME(rigid_aliases_marker): We probably want to assert that the rhs is rigid. + (GenericKind::Alias(a1), ty::Alias(_, a2)) + if a1.kind.def_id() == a2.kind.def_id() => {} _ => return None, } diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index 03bcb5215ee1a..067953fa5b6d4 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -805,7 +805,9 @@ impl<'tcx> GenericKind<'tcx> { match *self { GenericKind::Param(ref p) => p.to_ty(tcx), GenericKind::Placeholder(ref p) => Ty::new_placeholder(tcx, *p), - GenericKind::Alias(ref p) => p.to_ty(tcx), + // FIXME(rigid_aliases_marker): We probably want all uses of `GenericKind` to + // already be fully normalized. + GenericKind::Alias(ref p) => p.to_ty(tcx, ty::IsRigid::No), } } } diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 8c296289fef0c..1f868335af02c 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -467,7 +467,7 @@ impl<'tcx> Generalizer<'_, 'tcx> { let is_nested_alias = mem::replace(&mut self.in_alias, true); let result = match self.relate(alias, alias) { - Ok(alias) => Ok(alias.to_term(self.cx())), + Ok(alias) => Ok(alias.to_term(self.cx(), ty::IsRigid::No)), Err(e) => { if is_nested_alias { return Err(e); @@ -636,7 +636,8 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { } } - ty::Alias(data) => match self.structurally_relate_aliases { + // We shouldn't perform lazy norm for rigid aliases. + ty::Alias(ty::IsRigid::No, data) => match self.structurally_relate_aliases { StructurallyRelateAliases::No => { self.generalize_alias_term(data.into()).map(|v| v.expect_type()) } @@ -752,24 +753,32 @@ 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 { - // 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. - StructurallyRelateAliases::No if !tcx.features().generic_const_exprs() => { - self.generalize_alias_term(uv.into()).map(|v| v.expect_const()) - } - _ => { - let ty::UnevaluatedConst { kind, args, .. } = uv; - let args = self.relate_with_variance( - ty::Invariant, - ty::VarianceDiagInfo::default(), - args, - args, - )?; - Ok(ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(tcx, kind, args))) + // + // We shouldn't perform lazy norm for rigid aliases. + ty::ConstKind::Unevaluated(ty::IsRigid::No, uv) => { + 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. + StructurallyRelateAliases::No if !tcx.features().generic_const_exprs() => { + self.generalize_alias_term(uv.into()).map(|v| v.expect_const()) + } + _ => { + let ty::UnevaluatedConst { kind, args, .. } = uv; + let args = self.relate_with_variance( + ty::Invariant, + ty::VarianceDiagInfo::default(), + args, + args, + )?; + Ok(ty::Const::new_unevaluated( + tcx, + ty::IsRigid::No, + ty::UnevaluatedConst::new(tcx, kind, args), + )) + } } - }, + } ty::ConstKind::Placeholder(placeholder) => { if self.for_universe.can_name(placeholder.universe) { Ok(c) diff --git a/compiler/rustc_infer/src/infer/relate/lattice.rs b/compiler/rustc_infer/src/infer/relate/lattice.rs index bb09b50fd8ae2..2c14a7d44e8c6 100644 --- a/compiler/rustc_infer/src/infer/relate/lattice.rs +++ b/compiler/rustc_infer/src/infer/relate/lattice.rs @@ -161,12 +161,12 @@ impl<'tcx> TypeRelation> for LatticeOp<'_, 'tcx> { } ( - &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id: a_def_id }, .. }), - &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id: b_def_id }, .. }), + &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: a_def_id }, .. }), + &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: b_def_id }, .. }), ) if a_def_id == b_def_id => super_combine_tys(infcx, self, a, b), - (&ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }), _) - | (_, &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. })) + (&ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }), _) + | (_, &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. })) if def_id.is_local() && !infcx.next_trait_solver() => { self.register_goals(infcx.handle_opaque_type( diff --git a/compiler/rustc_infer/src/infer/relate/type_relating.rs b/compiler/rustc_infer/src/infer/relate/type_relating.rs index 595392fcfb524..b4a55385e8a7c 100644 --- a/compiler/rustc_infer/src/infer/relate/type_relating.rs +++ b/compiler/rustc_infer/src/infer/relate/type_relating.rs @@ -184,14 +184,14 @@ impl<'tcx> TypeRelation> for TypeRelating<'_, 'tcx> { } ( - &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id: a_def_id }, .. }), - &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id: b_def_id }, .. }), + &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: a_def_id }, .. }), + &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: b_def_id }, .. }), ) if a_def_id == b_def_id => { super_combine_tys(infcx, self, a, b)?; } - (&ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }), _) - | (_, &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. })) + (&ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }), _) + | (_, &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. })) if self.define_opaque_types == DefineOpaqueTypes::Yes && def_id.is_local() => { self.register_goals(infcx.handle_opaque_type( diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 4ea1a3f1209e4..fa6b40718a836 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -848,7 +848,7 @@ impl<'tcx> LateContext<'tcx> { tcx.associated_items(trait_id) .find_by_ident_and_kind(tcx, Ident::with_dummy_span(name), ty::AssocTag::Type, trait_id) .and_then(|assoc| { - let proj = Ty::new_projection(tcx, assoc.def_id, [self_ty]); + let proj = Ty::new_projection(tcx, ty::IsRigid::No, assoc.def_id, [self_ty]); tcx.try_normalize_erasing_regions(self.typing_env(), Unnormalized::new_wip(proj)) .ok() }) diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index df12502c7e5a8..5e68082b81a46 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -355,16 +355,16 @@ fn structurally_same_type_impl<'tcx>( | (ty::Coroutine(..), ty::Coroutine(..)) | (ty::CoroutineWitness(..), ty::CoroutineWitness(..)) | ( - ty::Alias(ty::AliasTy { kind: ty::Projection { .. }, .. }), - ty::Alias(ty::AliasTy { kind: ty::Projection { .. }, .. }), + ty::Alias(_, ty::AliasTy { kind: ty::Projection { .. }, .. }), + ty::Alias(_, ty::AliasTy { kind: ty::Projection { .. }, .. }), ) | ( - ty::Alias(ty::AliasTy { kind: ty::Inherent { .. }, .. }), - ty::Alias(ty::AliasTy { kind: ty::Inherent { .. }, .. }), + ty::Alias(_, ty::AliasTy { kind: ty::Inherent { .. }, .. }), + ty::Alias(_, ty::AliasTy { kind: ty::Inherent { .. }, .. }), ) | ( - ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }), - ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }), + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }), + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }), ) => false, // These definitely should have been caught above. diff --git a/compiler/rustc_lint/src/gpukernel_abi.rs b/compiler/rustc_lint/src/gpukernel_abi.rs index d24e934fc06fe..e09687bc49114 100644 --- a/compiler/rustc_lint/src/gpukernel_abi.rs +++ b/compiler/rustc_lint/src/gpukernel_abi.rs @@ -115,7 +115,7 @@ impl<'tcx> TypeFolder> for CheckGpuKernelTypes<'tcx> { } ty::Adt(_, _) - | ty::Alias(_) + | ty::Alias(_, _) | ty::Array(_, _) | ty::Bound(_, _) | ty::Closure(_, _) diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index 842a9be7093a7..3859b0cab2520 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -243,12 +243,12 @@ where return; } - if let ty::Alias(ty::AliasTy { kind: ty::Projection { def_id }, args, .. }) = *t.kind() + if let ty::Alias(_, ty::AliasTy { kind: ty::Projection { def_id }, args, .. }) = *t.kind() && self.tcx.is_impl_trait_in_trait(def_id) { // visit the opaque of the RPITIT self.tcx.type_of(def_id).instantiate(self.tcx, args).skip_norm_wip().visit_with(self) - } else if let ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args: opaque_ty_args, .. }) = *t.kind() + } else if let ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args: opaque_ty_args, .. }) = *t.kind() && let Some(opaque_def_id) = def_id.as_local() // Don't recurse infinitely on an opaque && self.seen.insert(opaque_def_id) diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 3fb929aa92216..ed71ff6a463db 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -103,7 +103,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { let Some(proj_term) = proj.term.as_type() else { return }; // HACK: `impl Trait` from an RPIT is "ok"... - if let ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id: opaque_def_id }, .. }) = + if let ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: opaque_def_id }, .. }) = *proj_term.kind() && cx.tcx.parent(opaque_def_id) == def_id && matches!( @@ -130,7 +130,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { return; } - let proj_ty = proj.projection_term.expect_ty().to_ty(cx.tcx); + let proj_ty = proj.projection_term.expect_ty().to_ty(cx.tcx,ty::IsRigid::No); // For every instance of the projection type in the bounds, // replace them with the term we're assigning to the associated // type in our opaque type. @@ -177,7 +177,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { // then we can emit a suggestion to add the bound. let add_bound = match (proj_term.kind(), assoc_pred.kind().skip_binder()) { ( - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }), + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }), ty::ClauseKind::Trait(trait_pred), ) => Some(AddBound { suggest_span: cx.tcx.def_span(*def_id).shrink_to_hi(), @@ -192,6 +192,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { OpaqueHiddenInferredBoundLint { ty: Ty::new_opaque( cx.tcx, + ty::IsRigid::No, def_id, ty::GenericArgs::identity_for_item(cx.tcx, def_id), ), diff --git a/compiler/rustc_lint/src/types/improper_ctypes.rs b/compiler/rustc_lint/src/types/improper_ctypes.rs index b086d7e1fedb9..db59ddfb9efa6 100644 --- a/compiler/rustc_lint/src/types/improper_ctypes.rs +++ b/compiler/rustc_lint/src/types/improper_ctypes.rs @@ -889,16 +889,18 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // While opaque types are checked for earlier, if a projection in a struct field // normalizes to an opaque type, then it will reach this branch. - ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }) => { FfiUnsafe { ty, reason: msg!("opaque types have no C equivalent"), help: None } } // `extern "C" fn` functions can have type parameters, which may or may not be FFI-safe, // so they are currently ignored for the purposes of this lint. ty::Param(..) - | ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. }, .. - }) if state.can_expect_ty_params() => FfiSafe, + | ty::Alias(_, ty::AliasTy { kind: ty::Projection { .. } | ty::Inherent { .. }, .. }) + if state.can_expect_ty_params() => + { + FfiSafe + } ty::UnsafeBinder(_) => FfiUnsafe { ty, @@ -920,10 +922,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { }, ty::Param(..) - | ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }, - .. - }) + | ty::Alias( + _, + ty::AliasTy { + kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }, + .. + }, + ) | ty::Infer(..) | ty::Bound(..) | ty::Error(_) @@ -942,7 +947,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return ControlFlow::Continue(()); } - if let ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }) = ty.kind() { + if let ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }) = ty.kind() { ControlFlow::Break(ty) } else { ty.super_visit_with(self) diff --git a/compiler/rustc_lint/src/unused/must_use.rs b/compiler/rustc_lint/src/unused/must_use.rs index 293320d868a66..c7177f1829bbd 100644 --- a/compiler/rustc_lint/src/unused/must_use.rs +++ b/compiler/rustc_lint/src/unused/must_use.rs @@ -176,10 +176,12 @@ pub fn is_ty_must_use<'tcx>( ty::Adt(def, _) => { is_def_must_use(cx, def.did(), expr.span).map_or(IsTyMustUse::No, IsTyMustUse::Yes) } - ty::Alias(ty::AliasTy { - kind: ty::Opaque { def_id: def } | ty::Projection { def_id: def }, - .. - }) => { + ty::Alias( + _, + ty::AliasTy { + kind: ty::Opaque { def_id: def } | ty::Projection { def_id: def }, .. + }, + ) => { elaborate( cx.tcx, cx.tcx @@ -296,7 +298,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { if let hir::ExprKind::Match(await_expr, _arms, hir::MatchSource::AwaitDesugar) = expr.kind && let ty = cx.typeck_results().expr_ty(await_expr) - && let ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id: future_def_id }, .. }) = ty.kind() + && let ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: future_def_id }, .. }) = ty.kind() && cx.tcx.ty_is_opaque_future(ty) && let async_fn_def_id = cx.tcx.parent(*future_def_id) && matches!(cx.tcx.def_kind(async_fn_def_id), DefKind::Fn | DefKind::AssocFn) diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index cbd6afd68473a..bc1c1d8240559 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -14,7 +14,7 @@ use rustc_middle::middle::stability::DeprecationEntry; use rustc_middle::queries::ExternProviders; use rustc_middle::query::LocalCrate; use rustc_middle::ty::fast_reject::SimplifiedType; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt, TypeVisitable}; use rustc_middle::util::Providers; use rustc_serialize::Decoder; use rustc_session::StableCrateId; @@ -39,10 +39,11 @@ impl ProcessQueryValue<'_, T> for T { } } -impl<'tcx, T> ProcessQueryValue<'tcx, ty::EarlyBinder<'tcx, T>> for T { +// The `TypeVisitable` bound here is merely for `EarlyBinder`'s rigidness check. +impl<'tcx, T: TypeVisitable>> 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) + 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 39c73350f7e41..7e3b65391a29c 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)] @@ -317,7 +320,7 @@ impl<'tcx> Const<'tcx> { ) -> Result { match self { Const::Ty(_, c) => { - if c.has_non_region_param() { + if c.has_non_region_param() || c.has_non_region_placeholders() { return Err(ErrorHandled::TooGeneric(span)); } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 21cee8b3845d4..bddfae79363e8 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/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 942c36f343343..5dab8392c9186 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1491,7 +1491,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { let val = match const_ { Const::Ty(_, ct) => match ct.kind() { ty::ConstKind::Param(p) => format!("ty::Param({p})"), - ty::ConstKind::Unevaluated(uv) => { + ty::ConstKind::Unevaluated(_is_rigid, uv) => { let kind = match uv.kind { ty::UnevaluatedConstKind::Projection { def_id } | ty::UnevaluatedConstKind::Inherent { def_id } diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 346a26a685317..e840217117769 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -385,7 +385,7 @@ fn def_id_of_type_cached<'a>(ty: Ty<'a>, visited: &mut SsoHashSet>) -> Op | ty::CoroutineWitness(def_id, _) | ty::Foreign(def_id) => Some(def_id), - ty::Alias(alias) => Some(alias.kind.def_id()), + ty::Alias(_is_rigid, alias) => Some(alias.kind.def_id()), ty::Bool | ty::Char diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index ac38053d153cc..03aaf575292cf 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -52,7 +52,9 @@ impl<'tcx> TyCtxt<'tcx> { } fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> { let ct = match c.kind() { - ty::ConstKind::Unevaluated(uv) if let Some(def_id) = uv.kind.opt_def_id() => { + ty::ConstKind::Unevaluated(_is_rigid, uv) + if let Some(def_id) = uv.kind.opt_def_id() => + { match self.tcx.thir_abstract_const(def_id) { Err(e) => ty::Const::new_error(self.tcx, e), Ok(Some(bac)) => { diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index e26dac94edd16..d380b7f522636 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_iter( self.all_fields().map(move |field| tcx.type_of(field.did).skip_binder()), ) } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 30d9a9fb1650c..3455e770b40d1 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -107,8 +107,12 @@ impl<'tcx> Const<'tcx> { } #[inline] - pub fn new_unevaluated(tcx: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Unevaluated(uv)) + pub fn new_unevaluated( + tcx: TyCtxt<'tcx>, + is_rigid: ty::IsRigid, + uv: ty::UnevaluatedConst<'tcx>, + ) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Unevaluated(is_rigid, uv)) } #[inline] @@ -190,8 +194,12 @@ impl<'tcx> rustc_type_ir::inherent::Const> for Const<'tcx> { Const::new_placeholder(tcx, placeholder) } - fn new_unevaluated(interner: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Self { - Const::new_unevaluated(interner, uv) + fn new_unevaluated( + interner: TyCtxt<'tcx>, + is_rigid: ty::IsRigid, + uv: ty::UnevaluatedConst<'tcx>, + ) -> Self { + Const::new_unevaluated(interner, is_rigid, uv) } fn new_expr(interner: TyCtxt<'tcx>, expr: ty::Expr<'tcx>) -> Self { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index d6bf72e215e7c..f40939b469ce9 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2064,7 +2064,8 @@ impl<'tcx> TyCtxt<'tcx> { /// Given a `ty`, return whether it's an `impl Future<...>`. pub fn ty_is_opaque_future(self, ty: Ty<'_>) -> bool { - let ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }) = *ty.kind() else { + let ty::Alias(_is_rigid, ty::AliasTy { kind: ty::Opaque { def_id }, .. }) = *ty.kind() + else { return false; }; let future_trait = self.require_lang_item(LangItem::Future, DUMMY_SP); @@ -2696,6 +2697,10 @@ impl<'tcx> TyCtxt<'tcx> { self.sess.opts.unstable_opts.disable_fast_paths } + pub fn renormalize_rigid_aliases(self) -> bool { + self.sess.opts.unstable_opts.renormalize_rigid_aliases + } + #[allow(rustc::bad_opt_access)] pub fn use_typing_mode_post_typeck_until_borrowck(self) -> bool { self.next_trait_solver_globally() diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index c6989ddd36199..50c425baca12c 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -340,6 +340,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.assumptions_on_binders() } + fn renormalize_rigid_aliases(self) -> bool { + self.renormalize_rigid_aliases() + } + fn coroutine_hidden_types( self, def_id: DefId, @@ -388,7 +392,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self, def_id: DefId, ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { - ty::EarlyBinder::bind( + ty::EarlyBinder::bind_iter( self.predicates_of(def_id) .instantiate_identity(self) .predicates @@ -401,7 +405,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self, def_id: DefId, ) -> ty::EarlyBinder<'tcx, impl IntoIterator>> { - ty::EarlyBinder::bind( + ty::EarlyBinder::bind_iter( self.predicates_of(def_id) .instantiate_own_identity() .map(|(clause, _)| clause.skip_normalization()), @@ -456,7 +460,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self, def_id: DefId, ) -> ty::EarlyBinder<'tcx, impl IntoIterator>>> { - ty::EarlyBinder::bind( + ty::EarlyBinder::bind_iter( self.const_conditions(def_id) .instantiate_identity(self) .into_iter() @@ -468,7 +472,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self, def_id: DefId, ) -> ty::EarlyBinder<'tcx, impl IntoIterator>>> { - ty::EarlyBinder::bind( + ty::EarlyBinder::bind_iter( self.explicit_implied_const_bounds(def_id) .iter_identity_copied() .map(Unnormalized::skip_normalization) @@ -645,7 +649,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> { // // Impls which apply to an alias after normalization are handled by // `assemble_candidates_after_normalizing_self_ty`. - ty::Alias(_) | ty::Placeholder(..) | ty::Error(_) => (), + ty::Alias(ty::IsRigid::Yes, _) | ty::Placeholder(..) | ty::Error(_) => (), + // Need to support aliases not marked as rigid for the old solver. + ty::Alias(ty::IsRigid::No, _) => (), // FIXME: These should ideally not exist as a self type. It would be nice for // the builtin auto trait impls of coroutines to instead directly recurse diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index a9e7425fdcbf6..ea988478c26b6 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -627,12 +627,14 @@ impl<'tcx> TypeVisitor> for IsSuggestableVisitor<'tcx> { return ControlFlow::Break(()); } - Alias(AliasTy { kind: Opaque { def_id }, .. }) => { + Alias(_is_rigid, AliasTy { kind: Opaque { def_id }, .. }) => { let parent = self.tcx.parent(def_id); let parent_ty = self.tcx.type_of(parent).instantiate_identity().skip_norm_wip(); if let DefKind::TyAlias | DefKind::AssocTy = self.tcx.def_kind(parent) - && let Alias(AliasTy { kind: Opaque { def_id: parent_opaque_def_id }, .. }) = - *parent_ty.kind() + && let Alias( + _is_rigid, + AliasTy { kind: Opaque { def_id: parent_opaque_def_id }, .. }, + ) = *parent_ty.kind() && parent_opaque_def_id == def_id { // Okay @@ -641,7 +643,7 @@ impl<'tcx> TypeVisitor> for IsSuggestableVisitor<'tcx> { } } - Alias(AliasTy { kind: Projection { def_id }, .. }) + Alias(_is_rigid, AliasTy { kind: Projection { def_id }, .. }) if self.tcx.def_kind(def_id) != DefKind::AssocTy => { return ControlFlow::Break(()); @@ -715,13 +717,15 @@ impl<'tcx> FallibleTypeFolder> for MakeSuggestableFolder<'tcx> { placeholder } - Alias(AliasTy { kind: Opaque { def_id }, .. }) => { + Alias(_is_rigid, AliasTy { kind: Opaque { def_id }, .. }) => { let parent = self.tcx.parent(def_id); let parent_ty = self.tcx.type_of(parent).instantiate_identity().skip_norm_wip(); if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent) - && let Alias(AliasTy { kind: Opaque { def_id: parent_opaque_def_id }, .. }) = - *parent_ty.kind() + && let Alias( + _is_rigid, + AliasTy { kind: Opaque { def_id: parent_opaque_def_id }, .. }, + ) = *parent_ty.kind() && parent_opaque_def_id == def_id { t diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index 8dda3603df9df..ff60a61cecb60 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -148,11 +148,12 @@ impl<'tcx> Ty<'tcx> { ty::Infer(ty::FreshTy(_)) => "fresh type".into(), ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(), ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(), - ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. }, .. - }) => "associated type".into(), + ty::Alias( + _is_rigid, + ty::AliasTy { kind: ty::Projection { .. } | ty::Inherent { .. }, .. }, + ) => "associated type".into(), ty::Param(p) => format!("type parameter `{p}`").into(), - ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }) => { + ty::Alias(_is_rigid, ty::AliasTy { kind: ty::Opaque { .. }, .. }) => { if tcx.ty_is_opaque_future(self) { "future".into() } else { "opaque type".into() } } ty::Error(_) => "type error".into(), @@ -207,12 +208,15 @@ impl<'tcx> Ty<'tcx> { ty::Tuple(..) => "tuple".into(), ty::Placeholder(..) => "higher-ranked type".into(), ty::Bound(..) => "bound type variable".into(), - ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. }, .. - }) => "associated type".into(), - ty::Alias(ty::AliasTy { kind: ty::Free { .. }, .. }) => "type alias".into(), + ty::Alias( + _is_rigid, + ty::AliasTy { kind: ty::Projection { .. } | ty::Inherent { .. }, .. }, + ) => "associated type".into(), + ty::Alias(_is_rigid, ty::AliasTy { kind: ty::Free { .. }, .. }) => "type alias".into(), ty::Param(_) => "type parameter".into(), - ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }) => "opaque type".into(), + ty::Alias(_is_rigid, ty::AliasTy { kind: ty::Opaque { .. }, .. }) => { + "opaque type".into() + } } } } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 84e0b37a7f7d0..3a2aca6c6896e 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -385,8 +385,9 @@ impl<'tcx> GenericPredicates<'tcx> { args: GenericArgsRef<'tcx>, ) -> impl Iterator>, Span)> + DoubleEndedIterator - + ExactSizeIterator { - EarlyBinder::bind(self.predicates).iter_instantiated_copied(tcx, args).map(|u| { + + ExactSizeIterator + + Clone { + EarlyBinder::bind_iter(self.predicates).iter_instantiated_copied(tcx, args).map(|u| { let (clause, span) = u.unzip(); (clause, span.skip_normalization()) }) @@ -396,8 +397,9 @@ impl<'tcx> GenericPredicates<'tcx> { self, ) -> impl Iterator>, Span)> + DoubleEndedIterator - + ExactSizeIterator { - EarlyBinder::bind(self.predicates).iter_identity_copied().map(|u| { + + ExactSizeIterator + + Clone { + EarlyBinder::bind_iter(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)); } @@ -465,8 +467,9 @@ impl<'tcx> ConstConditions<'tcx> { args: GenericArgsRef<'tcx>, ) -> impl Iterator>, Span)> + DoubleEndedIterator - + ExactSizeIterator { - EarlyBinder::bind(self.predicates).iter_instantiated_copied(tcx, args).map(|u| { + + ExactSizeIterator + + Clone { + EarlyBinder::bind_iter(self.predicates).iter_instantiated_copied(tcx, args).map(|u| { let (trait_ref, span) = u.unzip(); (trait_ref, span.skip_normalization()) }) @@ -476,8 +479,9 @@ impl<'tcx> ConstConditions<'tcx> { self, ) -> impl Iterator>, Span)> + DoubleEndedIterator - + ExactSizeIterator { - EarlyBinder::bind(self.predicates).iter_identity_copied().map(|u| { + + ExactSizeIterator + + Clone { + EarlyBinder::bind_iter(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/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 6aff85e77da5a..49e66a79477e8 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -113,12 +113,16 @@ impl<'tcx> Ty<'tcx> { InhabitedPredicate::True } Never => InhabitedPredicate::False, + // FIXME(rigid_aliases_marker): This should only encounter rigid aliases with the new solver. Param(_) - | Alias(ty::AliasTy { - kind: ty::Inherent { .. } | ty::Projection { .. } | ty::Free { .. }, - .. - }) => InhabitedPredicate::GenericType(self), - &Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => { + | Alias( + _, + ty::AliasTy { + kind: ty::Inherent { .. } | ty::Projection { .. } | ty::Free { .. }, + .. + }, + ) => InhabitedPredicate::GenericType(self), + &Alias(_is_rigid, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => { match def_id.as_local() { // Foreign opaque is considered inhabited. None => InhabitedPredicate::True, diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index f85355330d6b8..6bf119bdf7a9c 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -861,11 +861,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/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index a0dd7b5c5cb5e..4b64e9a767213 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -408,11 +408,13 @@ impl<'tcx> SizeSkeleton<'tcx> { ); match tail.kind() { + // FIXME(rigid_aliases_marker): This should only handle rigid aliases if we're using + // the new solver. ty::Param(_) - | ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. }, - .. - }) => { + | ty::Alias( + _, + ty::AliasTy { kind: ty::Projection { .. } | ty::Inherent { .. }, .. }, + ) => { debug_assert!(tail.has_non_region_param()); Ok(SizeSkeleton::Pointer { non_zero, @@ -915,7 +917,12 @@ where { let metadata = tcx.normalize_erasing_regions( cx.typing_env(), - Unnormalized::new(Ty::new_projection(tcx, metadata_def_id, [pointee])), + Unnormalized::new(Ty::new_projection( + tcx, + ty::IsRigid::No, + metadata_def_id, + [pointee], + )), ); // Map `Metadata = DynMetadata` back to a vtable, since it diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 3d8ab41b37a31..9087fb549dba5 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -687,16 +687,29 @@ impl<'tcx> Term<'tcx> { pub fn to_alias_term(self) -> Option> { match self.kind() { TermKind::Ty(ty) => match *ty.kind() { - ty::Alias(alias_ty) => Some(alias_ty.into()), + ty::Alias(_, alias_ty) => Some(alias_ty.into()), _ => None, }, TermKind::Const(ct) => match ct.kind() { - ConstKind::Unevaluated(uv) => Some(uv.into()), + ConstKind::Unevaluated(_, uv) => Some(uv.into()), _ => None, }, } } + pub fn is_non_rigid_alias(self) -> bool { + match self.kind() { + ty::TermKind::Ty(ty) => match ty.kind() { + ty::Alias(ty::IsRigid::No, _) => true, + _ => false, + }, + ty::TermKind::Const(ct) => match ct.kind() { + ty::ConstKind::Unevaluated(ty::IsRigid::No, _) => true, + _ => false, + }, + } + } + pub fn is_infer(&self) -> bool { match self.kind() { TermKind::Ty(ty) => ty.is_ty_var(), @@ -925,7 +938,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) } } } @@ -953,7 +966,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/offload_meta.rs b/compiler/rustc_middle/src/ty/offload_meta.rs index 6303520383fbd..9d0fcc50ef224 100644 --- a/compiler/rustc_middle/src/ty/offload_meta.rs +++ b/compiler/rustc_middle/src/ty/offload_meta.rs @@ -119,7 +119,8 @@ impl MappingFlags { MappingFlags::LITERAL | MappingFlags::IMPLICIT } - ty::Adt(_, _) | ty::Tuple(_) | ty::Array(_, _) | ty::Alias(_) | ty::Param(_) => { + // FIXME: This should not treat aliases this way. + ty::Adt(_, _) | ty::Tuple(_) | ty::Array(_, _) | ty::Alias(_, _) | ty::Param(_) => { MappingFlags::TO } 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 1926930333629..759b34ed98bdf 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -820,13 +820,14 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } ty::Foreign(def_id) => self.print_def_path(def_id, &[])?, ty::Alias( + _is_rigid, ref data @ ty::AliasTy { kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }, .. }, ) => data.print(self)?, ty::Placeholder(placeholder) => placeholder.print(self)?, - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => { + ty::Alias(_is_rigid, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => { // We use verbose printing in 'NO_QUERIES' mode, to // avoid needing to call `predicates_of`. This should // only affect certain debug messages (e.g. messages printed @@ -846,7 +847,10 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { DefKind::TyAlias | DefKind::AssocTy => { // NOTE: I know we should check for NO_QUERIES here, but it's alright. // `type_of` on a type alias or assoc type should never cause a cycle. - if let ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id: d }, .. }) = *self + if let ty::Alias( + _is_rigid, + ty::AliasTy { kind: ty::Opaque { def_id: d }, .. }, + ) = *self .tcx() .type_of(parent) .instantiate_identity() @@ -1367,7 +1371,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { let fn_args = if self.tcx().features().return_type_notation() && let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) = self.tcx().opt_rpitit_info(def_id) - && let ty::Alias(alias_ty) = + && let ty::Alias(_is_rigid, alias_ty) = self.tcx().fn_sig(fn_def_id).skip_binder().output().skip_binder().kind() && alias_ty.kind.def_id() == def_id && let generics = self.tcx().generics_of(fn_def_id) @@ -1562,7 +1566,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { } match ct.kind() { - ty::ConstKind::Unevaluated(ty::UnevaluatedConst { kind, args, .. }) => { + ty::ConstKind::Unevaluated(_is_rigid, ty::UnevaluatedConst { kind, args, .. }) => { match kind { ty::UnevaluatedConstKind::Projection { def_id } | ty::UnevaluatedConstKind::Inherent { def_id } diff --git a/compiler/rustc_middle/src/ty/significant_drop_order.rs b/compiler/rustc_middle/src/ty/significant_drop_order.rs index e680e62f50931..c5b50163fbbb1 100644 --- a/compiler/rustc_middle/src/ty/significant_drop_order.rs +++ b/compiler/rustc_middle/src/ty/significant_drop_order.rs @@ -133,7 +133,7 @@ pub fn ty_dtor_span<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { | ty::FnPtr(_, _) | ty::Tuple(_) | ty::Dynamic(_, _) - | ty::Alias(_) + | ty::Alias(_, _) | ty::Bound(_, _) | ty::Pat(_, _) | ty::Placeholder(_) diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index a92a407133e32..a4bd403657a26 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -371,7 +371,7 @@ impl<'tcx> TypeSuperFoldable> for Ty<'tcx> { ty::CoroutineClosure(did, args) => { ty::CoroutineClosure(did, args.try_fold_with(folder)?) } - ty::Alias(data) => ty::Alias(data.try_fold_with(folder)?), + ty::Alias(is_rigid, data) => ty::Alias(is_rigid, data.try_fold_with(folder)?), ty::Pat(ty, pat) => ty::Pat(ty.try_fold_with(folder)?, pat.try_fold_with(folder)?), ty::Bool @@ -410,7 +410,7 @@ impl<'tcx> TypeSuperFoldable> for Ty<'tcx> { ty::CoroutineWitness(did, args) => ty::CoroutineWitness(did, args.fold_with(folder)), ty::Closure(did, args) => ty::Closure(did, args.fold_with(folder)), ty::CoroutineClosure(did, args) => ty::CoroutineClosure(did, args.fold_with(folder)), - ty::Alias(data) => ty::Alias(data.fold_with(folder)), + ty::Alias(is_rigid, data) => ty::Alias(is_rigid, data.fold_with(folder)), ty::Pat(ty, pat) => ty::Pat(ty.fold_with(folder), pat.fold_with(folder)), ty::Bool @@ -458,7 +458,7 @@ impl<'tcx> TypeSuperVisitable> for Ty<'tcx> { ty::CoroutineWitness(_did, args) => args.visit_with(visitor), ty::Closure(_did, args) => args.visit_with(visitor), ty::CoroutineClosure(_did, args) => args.visit_with(visitor), - ty::Alias(data) => data.visit_with(visitor), + ty::Alias(_is_rigid, data) => data.visit_with(visitor), ty::Pat(ty, pat) => { try_visit!(ty.visit_with(visitor)); @@ -633,7 +633,9 @@ impl<'tcx> TypeSuperFoldable> for ty::Const<'tcx> { folder: &mut F, ) -> Result { let kind = match self.kind() { - ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.try_fold_with(folder)?), + ConstKind::Unevaluated(is_rigid, uv) => { + ConstKind::Unevaluated(is_rigid, uv.try_fold_with(folder)?) + } ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?), ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?), @@ -648,7 +650,9 @@ impl<'tcx> TypeSuperFoldable> for ty::Const<'tcx> { fn super_fold_with>>(self, folder: &mut F) -> Self { let kind = match self.kind() { - ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.fold_with(folder)), + ConstKind::Unevaluated(is_rigid, uv) => { + ConstKind::Unevaluated(is_rigid, uv.fold_with(folder)) + } ConstKind::Value(v) => ConstKind::Value(v.fold_with(folder)), ConstKind::Expr(e) => ConstKind::Expr(e.fold_with(folder)), @@ -665,7 +669,7 @@ impl<'tcx> TypeSuperFoldable> for ty::Const<'tcx> { impl<'tcx> TypeSuperVisitable> for ty::Const<'tcx> { fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { match self.kind() { - ConstKind::Unevaluated(uv) => uv.visit_with(visitor), + ConstKind::Unevaluated(_is_rigid, uv) => uv.visit_with(visitor), ConstKind::Value(v) => v.visit_with(visitor), ConstKind::Expr(e) => e.visit_with(visitor), ConstKind::Error(e) => e.visit_with(visitor), diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 9db9b1769ab9c..3d8efcae64392 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() } @@ -476,14 +476,18 @@ impl<'tcx> Ty<'tcx> { } #[inline] - pub fn new_alias(tcx: TyCtxt<'tcx>, alias_ty: ty::AliasTy<'tcx>) -> Ty<'tcx> { + pub fn new_alias( + tcx: TyCtxt<'tcx>, + is_rigid: ty::IsRigid, + alias_ty: ty::AliasTy<'tcx>, + ) -> Ty<'tcx> { debug_assert_matches!( (alias_ty.kind, tcx.def_kind(alias_ty.kind.def_id())), (ty::Opaque { .. }, DefKind::OpaqueTy) | (ty::Projection { .. } | ty::Inherent { .. }, DefKind::AssocTy) | (ty::Free { .. }, DefKind::TyAlias) ); - Ty::new(tcx, Alias(alias_ty)) + Ty::new(tcx, Alias(is_rigid, alias_ty)) } #[inline] @@ -522,8 +526,13 @@ 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)) + pub fn new_opaque( + tcx: TyCtxt<'tcx>, + is_rigid: ty::IsRigid, + def_id: DefId, + args: GenericArgsRef<'tcx>, + ) -> Ty<'tcx> { + Ty::new_alias(tcx, is_rigid, AliasTy::new_from_args(tcx, ty::Opaque { def_id }, args)) } /// Constructs a `TyKind::Error` type with current `ErrorGuaranteed` @@ -776,11 +785,13 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_projection_from_args( tcx: TyCtxt<'tcx>, + is_rigid: ty::IsRigid, item_def_id: DefId, args: ty::GenericArgsRef<'tcx>, ) -> Ty<'tcx> { Ty::new_alias( tcx, + is_rigid, AliasTy::new_from_args(tcx, ty::Projection { def_id: item_def_id }, args), ) } @@ -788,10 +799,15 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_projection( tcx: TyCtxt<'tcx>, + is_rigid: ty::IsRigid, 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, + is_rigid, + AliasTy::new(tcx, ty::Projection { def_id: item_def_id }, args), + ) } #[inline] @@ -967,8 +983,12 @@ impl<'tcx> rustc_type_ir::inherent::Ty> for Ty<'tcx> { Ty::new_canonical_bound(tcx, var) } - fn new_alias(interner: TyCtxt<'tcx>, alias_ty: ty::AliasTy<'tcx>) -> Self { - Ty::new_alias(interner, alias_ty) + fn new_alias( + interner: TyCtxt<'tcx>, + is_rigid: ty::IsRigid, + alias_ty: ty::AliasTy<'tcx>, + ) -> Self { + Ty::new_alias(interner, is_rigid, alias_ty) } fn new_error(interner: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self { @@ -1607,7 +1627,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn is_opaque(self) -> bool { - matches!(self.kind(), Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. })) + matches!(self.kind(), Alias(_is_rigid, ty::AliasTy { kind: ty::Opaque { .. }, .. })) } #[inline] @@ -1689,7 +1709,12 @@ impl<'tcx> Ty<'tcx> { let assoc_items = tcx.associated_item_def_ids( tcx.require_lang_item(hir::LangItem::DiscriminantKind, DUMMY_SP), ); - Ty::new_projection_from_args(tcx, assoc_items[0], tcx.mk_args(&[self.into()])) + Ty::new_projection_from_args( + tcx, + ty::IsRigid::No, + assoc_items[0], + tcx.mk_args(&[self.into()]), + ) } ty::Pat(ty, _) => ty.discriminant_ty(tcx), @@ -1822,7 +1847,7 @@ impl<'tcx> Ty<'tcx> { Ok(metadata_ty) => metadata_ty, Err(tail_ty) => { let metadata_def_id = tcx.require_lang_item(LangItem::Metadata, DUMMY_SP); - Ty::new_projection(tcx, metadata_def_id, [tail_ty]) + Ty::new_projection(tcx, ty::IsRigid::No, metadata_def_id, [tail_ty]) } } } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index ee6aaf9cb6e17..6ca4945c129da 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -894,12 +894,16 @@ impl<'tcx> TyCtxt<'tcx> { /// [free]: ty::Free /// [expand_free_alias_tys]: Self::expand_free_alias_tys pub fn peel_off_free_alias_tys(self, mut ty: Ty<'tcx>) -> Ty<'tcx> { - let ty::Alias(ty::AliasTy { kind: ty::Free { .. }, .. }) = ty.kind() else { return ty }; + let ty::Alias(_is_rigid, ty::AliasTy { kind: ty::Free { .. }, .. }) = ty.kind() else { + return ty; + }; let limit = self.recursion_limit(); let mut depth = 0; - while let &ty::Alias(ty::AliasTy { kind: ty::Free { def_id }, args, .. }) = ty.kind() { + while let &ty::Alias(_is_rigid, ty::AliasTy { kind: ty::Free { def_id }, args, .. }) = + ty.kind() + { if !limit.value_within_limit(depth) { let guar = self.dcx().delayed_bug("overflow expanding free alias type"); return Ty::new_error(self, guar); @@ -993,7 +997,9 @@ impl<'tcx> TypeFolder> for OpaqueTypeExpander<'tcx> { } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if let ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) = *t.kind() { + if let ty::Alias(_is_rigid, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) = + *t.kind() + { self.expand_opaque_ty(def_id, args).unwrap_or(t) } else if t.has_opaque_types() { t.super_fold_with(self) @@ -1037,7 +1043,8 @@ impl<'tcx> TypeFolder> for FreeAliasTypeExpander<'tcx> { if !ty.has_type_flags(ty::TypeFlags::HAS_TY_FREE_ALIAS) { return ty; } - let &ty::Alias(ty::AliasTy { kind: ty::Free { def_id }, args, .. }) = ty.kind() else { + let &ty::Alias(_is_rigid, ty::AliasTy { kind: ty::Free { def_id }, args, .. }) = ty.kind() + else { return ty.super_fold_with(self); }; if !self.tcx.recursion_limit().value_within_limit(self.depth) { diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index af270988abc9c..b18c56cc0fe83 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -181,15 +181,15 @@ impl<'tcx> TypeVisitor> for LateBoundRegionsCollector<'tcx> { match t.kind() { // If we are only looking for "constrained" regions, we have to ignore the // inputs to a projection as they may not appear in the normalized form. - ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Opaque { .. }, - .. - }) => { - return; - } - // All free alias types should've been expanded beforehand. - ty::Alias(ty::AliasTy { kind: ty::Free { .. }, .. }) => { - bug!("unexpected free alias type") + ty::Alias(_is_rigid, alias_ty) => { + match alias_ty.kind { + ty::Projection { .. } | ty::Inherent { .. } | ty::Opaque { .. } => return, + + // All free alias types should've been expanded beforehand. + ty::Free { .. } => { + bug!("unexpected free alias type") + } + } } _ => {} } diff --git a/compiler/rustc_mir_build/src/builder/block.rs b/compiler/rustc_mir_build/src/builder/block.rs index cfd9c4ec5d41a..47d231603d33b 100644 --- a/compiler/rustc_mir_build/src/builder/block.rs +++ b/compiler/rustc_mir_build/src/builder/block.rs @@ -335,7 +335,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if destination_ty.is_unit() || matches!( destination_ty.kind(), - ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }) + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }) ) { // We only want to assign an implicit `()` as the return value of the block if the 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 76360ee6c5b46..f0f7e166e9672 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -77,7 +77,7 @@ pub(crate) fn as_constant_inner<'tcx>( ty::UnevaluatedConstKind::new_from_def_id(tcx, def_id), args, ); - let ct = ty::Const::new_unevaluated(tcx, uneval); + let ct = ty::Const::new_unevaluated(tcx, ty::IsRigid::No, uneval); let const_ = Const::Ty(ty, ct); return ConstOperand { span, user_ty, const_ }; diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 178f79173ea50..0c271f776a30a 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -44,7 +44,7 @@ impl<'tcx, 'ptcx> PatCtxt<'tcx, 'ptcx> { let mut convert = ConstToPat::new(self, id, span, c); match c.kind() { - ty::ConstKind::Unevaluated(uv) => convert.unevaluated_to_pat(uv, ty), + ty::ConstKind::Unevaluated(_, uv) => convert.unevaluated_to_pat(uv, ty), ty::ConstKind::Value(value) => convert.valtree_to_pat(value), _ => span_bug!(span, "Invalid `ConstKind` for `const_to_pat`: {:?}", c), } @@ -72,7 +72,7 @@ impl<'tcx> ConstToPat<'tcx> { /// We errored. Signal that in the pattern, so that follow up errors can be silenced. fn mk_err(&self, mut err: Diag<'_>, ty: Ty<'tcx>) -> Box> { - if let ty::ConstKind::Unevaluated(uv) = self.c.kind() { + if let ty::ConstKind::Unevaluated(_, uv) = self.c.kind() { if let ty::UnevaluatedConstKind::Projection { def_id } | ty::UnevaluatedConstKind::Inherent { def_id } = uv.kind && let Some(def_id) = def_id.as_local() @@ -116,7 +116,7 @@ impl<'tcx> ConstToPat<'tcx> { self.tcx.dcx().create_err(CouldNotEvalConstPattern { span: self.span }); // We've emitted an error on the original const, it would be redundant to complain // on its use as well. - if let ty::ConstKind::Unevaluated(uv) = self.c.kind() + if let ty::ConstKind::Unevaluated(_, uv) = self.c.kind() && let ty::UnevaluatedConstKind::Projection { .. } | ty::UnevaluatedConstKind::Inherent { .. } | ty::UnevaluatedConstKind::Free { .. } = uv.kind diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 92cb9dd8de7ca..4bf69b3a85520 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -659,6 +659,7 @@ impl<'tcx, 'ptcx> PatCtxt<'tcx, 'ptcx> { // generic args, instead of how we represent them in body expressions. let c = ty::Const::new_unevaluated( self.tcx, + ty::IsRigid::No, ty::UnevaluatedConst::new( self.tcx, ty::UnevaluatedConstKind::new_from_def_id(self.tcx, def_id), diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index d7e0a819d7ea1..c9198da72c750 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -165,7 +165,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { | ty::Never | ty::Tuple(_) | ty::UnsafeBinder(_) - | ty::Alias(_) + | ty::Alias(_, _) | ty::Param(_) | ty::Bound(_, _) | ty::Infer(_) @@ -205,7 +205,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { | ty::CoroutineWitness(..) | ty::Never | ty::UnsafeBinder(_) - | ty::Alias(_) + | ty::Alias(_, _) | ty::Param(_) | ty::Bound(_, _) | ty::Infer(_) 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/coroutine/layout.rs b/compiler/rustc_mir_transform/src/coroutine/layout.rs index 7262d44dcab99..abf6894e7cde5 100644 --- a/compiler/rustc_mir_transform/src/coroutine/layout.rs +++ b/compiler/rustc_mir_transform/src/coroutine/layout.rs @@ -612,7 +612,7 @@ fn check_must_not_suspend_ty<'tcx>( } ty::Adt(def, _) => check_must_not_suspend_def(tcx, def.did(), hir_id, data), // FIXME: support adding the attribute to TAITs - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id: def }, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: def }, .. }) => { let mut has_emitted = false; for &(predicate, _) in tcx.explicit_item_bounds(def).skip_binder() { // We only look at the `DefId`, so it is safe to skip the binder here. 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 ca1aeedf10180..d88d9231c2009 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 bfd200884b676..567971084d260 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -419,9 +419,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 { @@ -637,7 +638,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/liveness.rs b/compiler/rustc_mir_transform/src/liveness.rs index 795b0b9cac82e..76e4f04f24303 100644 --- a/compiler/rustc_mir_transform/src/liveness.rs +++ b/compiler/rustc_mir_transform/src/liveness.rs @@ -235,6 +235,11 @@ fn maybe_drop_guard<'tcx>( ) -> bool { if ever_dropped.contains(index) { let ty = checked_places.places[index].ty(&body.local_decls, tcx).ty; + // FIXME(rigid_aliases_marker): ideally we set aliases to non_rigid right after + // the typing mode is set to `PostAnalysis`. + // But modifying local decls in MIR body is inconvenient. And we can't fold + // `PlaceRef` in `checked_places`. + let ty = ty::set_aliases_to_non_rigid(tcx, ty).skip_norm_wip(); matches!( ty.kind(), ty::Closure(..) @@ -244,7 +249,7 @@ fn maybe_drop_guard<'tcx>( | ty::Dynamic(..) | ty::Array(..) | ty::Slice(..) - | ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }) + | ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }) ) && ty.needs_drop(tcx, typing_env) } else { false diff --git a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs index 776840a6fe8b2..135cd5324e65d 100644 --- a/compiler/rustc_mir_transform/src/post_analysis_normalize.rs +++ b/compiler/rustc_mir_transform/src/post_analysis_normalize.rs @@ -4,7 +4,7 @@ use rustc_middle::mir::visit::*; use rustc_middle::mir::*; -use rustc_middle::ty::{self, Ty, TyCtxt, Unnormalized}; +use rustc_middle::ty::{self, Ty, TyCtxt}; pub(super) struct PostAnalysisNormalize; @@ -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, + ty::set_aliases_to_non_rigid(self.tcx, constant.const_), + ) { constant.const_ = c; } self.super_const_operand(constant, location); @@ -77,10 +77,21 @@ 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, + ty::set_aliases_to_non_rigid(self.tcx, *ty), + ) { *ty = t; } } + + #[inline] + fn visit_args(&mut self, args: &mut ty::GenericArgsRef<'tcx>, _: Location) { + if let Ok(a) = self.tcx.try_normalize_erasing_regions( + self.typing_env, + ty::set_aliases_to_non_rigid(self.tcx, *args), + ) { + *args = a; + } + } } diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 6bb70cee7603a..3f5ee93b91050 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -108,7 +108,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 e9c317ecdec21..1c11790d4be78 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -23,7 +23,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 @@ -203,7 +204,7 @@ fn build_adrop_for_coroutine_shim<'tcx>( let source_info = SourceInfo::outermost(span); 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 3dca3f09db65d..bbbae98cd49d0 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -679,7 +679,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { }; let kind = match parent_ty.ty.kind() { - &ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => { + &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => { self.tcx.type_of(def_id).instantiate(self.tcx, args).skip_norm_wip().kind() } kind => kind, @@ -783,7 +783,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 { @@ -1551,7 +1551,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { pty.kind(), ty::Adt(..) | ty::Coroutine(..) - | ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }) + | ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }) ) { self.fail( location, diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 0421edc543151..39dd84c26ae06 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 8b79eaae28753..0e30f1f3828e6 100644 --- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs +++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs @@ -242,7 +242,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 f0fe4c9056187..5fa2f49584f2c 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/canonical/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs index 824c78094a69b..c7697e5b78ecb 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs @@ -391,7 +391,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { | ty::CoroutineWitness(..) | ty::Never | ty::Tuple(_) - | ty::Alias(_) + | ty::Alias(_, _) | ty::Bound(_, _) | ty::Error(_) => { return ensure_sufficient_stack(|| t.super_fold_with(self)); @@ -565,7 +565,7 @@ impl, I: Interner> TypeFolder for Canonicaliz }, // FIXME: See comment above -- we could fold the region separately or something. ty::ConstKind::Bound(_, _) - | ty::ConstKind::Unevaluated(_) + | ty::ConstKind::Unevaluated(_, _) | ty::ConstKind::Value(_) | ty::ConstKind::Error(_) | ty::ConstKind::Expr(_) => return c.super_fold_with(self), diff --git a/compiler/rustc_next_trait_solver/src/canonical/mod.rs b/compiler/rustc_next_trait_solver/src/canonical/mod.rs index 6c6ead109e20e..80b4d3be172ef 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/mod.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/mod.rs @@ -333,7 +333,7 @@ where { let var_values = CanonicalVarValues { var_values: delegate.cx().mk_args(var_values) }; let state = inspect::State { var_values, data }; - let state = eager_resolve_vars(delegate, state); + let state = eager_resolve_vars(&**delegate, state); Canonicalizer::canonicalize_response(delegate, max_input_universe, state) } diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs index 589d055192029..6c346715a81c2 100644 --- a/compiler/rustc_next_trait_solver/src/coherence.rs +++ b/compiler/rustc_next_trait_solver/src/coherence.rs @@ -362,7 +362,7 @@ where // normalize to that, so we have to treat it as an uncovered ty param. // * Otherwise it may normalize to any non-type-generic type // be it local or non-local. - ty::Alias(ty::AliasTy { kind, .. }) => { + ty::Alias(_, ty::AliasTy { kind, .. }) => { if ty.has_type_flags( ty::TypeFlags::HAS_TY_PLACEHOLDER | ty::TypeFlags::HAS_TY_BOUND diff --git a/compiler/rustc_next_trait_solver/src/normalize.rs b/compiler/rustc_next_trait_solver/src/normalize.rs index 7506591d6fb5d..9ad5cb7209720 100644 --- a/compiler/rustc_next_trait_solver/src/normalize.rs +++ b/compiler/rustc_next_trait_solver/src/normalize.rs @@ -1,6 +1,8 @@ +use std::fmt::Debug; + 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::region_constraint::Assumptions; use rustc_type_ir::{ self as ty, Binder, FallibleTypeFolder, InferConst, InferCtxtLike, InferTy, Interner, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, @@ -21,7 +23,6 @@ where { infcx: &'a Infcx, universes: Vec>, - stalled_goals: Vec>, normalize: F, } @@ -31,6 +32,12 @@ enum HasEscapingBoundVars { No, } +#[derive(PartialEq, Eq)] +pub enum NormalizationWasAmbiguous { + Yes, + No, +} + /// Finds the max universe present in infer vars. struct MaxUniverse<'a, Infcx, I> where @@ -97,34 +104,27 @@ 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(I::Term) -> 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 } } fn normalize_alias_term( &mut self, alias_term: I::Term, has_escaping: HasEscapingBoundVars, - ) -> Result { + ) -> Result { let current_universe = self.infcx.universe(); self.infcx.create_next_universe(); + self.infcx + .insert_placeholder_assumptions(self.infcx.universe(), Some(Assumptions::empty())); - 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,7 +134,9 @@ 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 normalization_was_ambiguous == NormalizationWasAmbiguous::Yes + && has_escaping == HasEscapingBoundVars::Yes + { let mut visitor = MaxUniverse::new(self.infcx); normalized.visit_with(&mut visitor); let max_universe = visitor.max_universe(); @@ -143,18 +145,18 @@ where } } - self.stalled_goals.extend(ambig_goal); Ok(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(I::Term) -> Result<(I::Term, NormalizationWasAmbiguous), E>, + E: Debug, { - type Error = NoSolution; + type Error = E; fn cx(&self) -> I { self.infcx.cx() @@ -173,70 +175,105 @@ 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() { + let original = ty; + + if !self.cx().renormalize_rigid_aliases() && !ty.has_non_rigid_aliases() { 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) }; + let ty::Alias(orig_is_rigid, _) = ty.kind() else { return Ok(ty) }; + // We support ambiguous aliases inside rigid alias. So we still recognize + // the rigidness of the outer alias. + if !self.cx().renormalize_rigid_aliases() && orig_is_rigid == ty::IsRigid::Yes { + return Ok(ty); + } - if ty.has_escaping_bound_vars() { + let normalized = 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(|| { + let ty = ensure_sufficient_stack(|| { self.normalize_alias_term(ty.into(), HasEscapingBoundVars::Yes) })? .expect_ty(); - Ok(PlaceholderReplacer::replace_placeholders( + PlaceholderReplacer::replace_placeholders( infcx, mapped_regions, mapped_types, mapped_consts, &self.universes, - result, - )) + ty, + ) } else { - Ok(ensure_sufficient_stack(|| { + ensure_sufficient_stack(|| { self.normalize_alias_term(ty.into(), HasEscapingBoundVars::No) })? - .expect_ty()) + .expect_ty() + }; + + if self.cx().renormalize_rigid_aliases() && orig_is_rigid == ty::IsRigid::Yes { + // find out missing typing env change. + let original = crate::resolve::eager_resolve_vars(infcx, original); + let normalized = crate::resolve::eager_resolve_vars(infcx, normalized); + assert_eq!(original, normalized, "rigid alias is further normalized"); } + Ok(normalized) } #[instrument(level = "trace", skip(self), ret)] fn try_fold_const(&mut self, ct: I::Const) -> Result { let infcx = self.infcx; - if !ct.has_aliases() { + let original = ct; + + if !self.cx().renormalize_rigid_aliases() && !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(orig_is_rigid, _) = ct.kind() else { return Ok(ct) }; + // We support ambiguous aliases inside rigid alias. So we still recognize + // the rigidness of the outer alias. + if !self.cx().renormalize_rigid_aliases() && orig_is_rigid == ty::IsRigid::Yes { + return Ok(ct); + } - if ct.has_escaping_bound_vars() { + let normalized = 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(|| { + let ct = ensure_sufficient_stack(|| { self.normalize_alias_term(ct.into(), HasEscapingBoundVars::Yes) })? .expect_const(); - Ok(PlaceholderReplacer::replace_placeholders( + PlaceholderReplacer::replace_placeholders( infcx, mapped_regions, mapped_types, mapped_consts, &self.universes, - result, - )) + ct, + ) } else { - Ok(ensure_sufficient_stack(|| { + ensure_sufficient_stack(|| { self.normalize_alias_term(ct.into(), HasEscapingBoundVars::No) })? - .expect_const()) + .expect_const() + }; + + if self.cx().renormalize_rigid_aliases() && orig_is_rigid == ty::IsRigid::Yes { + // find out missing typing env change. + let original = crate::resolve::eager_resolve_vars(infcx, original); + let normalized = crate::resolve::eager_resolve_vars(infcx, normalized); + assert_eq!(original, normalized, "rigid alias is further normalized"); } + + Ok(normalized) + } + + 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..542cb476c2f38 100644 --- a/compiler/rustc_next_trait_solver/src/resolve.rs +++ b/compiler/rustc_next_trait_solver/src/resolve.rs @@ -5,15 +5,13 @@ use rustc_type_ir::{ TypeVisitableExt, }; -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, @@ -22,25 +20,25 @@ where cache: DelayedMap, } -pub fn eager_resolve_vars>( - delegate: &D, +pub fn eager_resolve_vars>( + infcx: &Infcx, value: T, ) -> T { if value.has_infer() { - let mut folder = EagerResolver::new(delegate); + let mut folder = EagerResolver::new(infcx); value.fold_with(&mut folder) } else { value } } -impl<'a, D: SolverDelegate> EagerResolver<'a, D> { - fn new(delegate: &'a D) -> Self { +impl<'a, Infcx: InferCtxtLike> EagerResolver<'a, Infcx> { + fn new(delegate: &'a Infcx) -> Self { EagerResolver { delegate, cache: Default::default() } } } -impl, I: Interner> TypeFolder for EagerResolver<'_, D> { +impl, I: Interner> TypeFolder for EagerResolver<'_, Infcx> { 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 b7e2101577eb2..bf82985ae559a 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 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 d89f80eca8303..0f2c158eec9a3 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(_) => { @@ -790,9 +790,14 @@ where } ty::Alias( + ty::IsRigid::Yes, alias_ty @ AliasTy { kind: ty::Projection { .. } | ty::Opaque { .. }, .. }, ) => alias_ty, - ty::Alias(AliasTy { kind: ty::Inherent { .. } | ty::Free { .. }, .. }) => { + ty::Alias(ty::IsRigid::No, _) => unreachable!("non-rigid self type: {self_ty:?}"), + ty::Alias( + ty::IsRigid::Yes, + AliasTy { kind: ty::Inherent { .. } | ty::Free { .. }, .. }, + ) => { self.cx().delay_bug(format!("could not normalize {self_ty:?}, it is not WF")); return Ok(()); } @@ -968,7 +973,7 @@ where elaborate::elaborate(cx, [predicate]) .skip(1) .map(|predicate| goal.with(cx, predicate)), - ); + )?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } }) @@ -1085,7 +1090,7 @@ where self.cx } fn fold_ty(&mut self, ty: I::Ty) -> I::Ty { - if let ty::Alias(alias_ty) = ty.kind() { + if let ty::Alias(_is_rigid, alias_ty) = ty.kind() { if alias_ty == self.alias_ty { return self.self_ty; } diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 2464d607f20ad..3552cd14d0a4c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -49,11 +49,14 @@ where ty::Dynamic(..) | ty::Param(..) - | ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }, - .. - }) + | ty::Alias( + ty::IsRigid::Yes, + ty::AliasTy { + kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }, .. + }, + ) | ty::Placeholder(..) + | ty::Alias(ty::IsRigid::No, _) | ty::Bound(..) | ty::Infer(_) => { panic!("unexpected type `{ty:?}`") @@ -102,7 +105,7 @@ where .collect(), )), - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => { + ty::Alias(ty::IsRigid::Yes, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => { // We can resolve the `impl Trait` to its concrete type, // which enforces a DAG between the functions requiring // the auto trait bounds in question. @@ -227,15 +230,10 @@ where | ty::Foreign(..) | ty::Ref(_, _, Mutability::Mut) | ty::Adt(_, _) - | ty::Alias(_) + | ty::Alias(ty::IsRigid::Yes, _) | ty::Param(_) | ty::Placeholder(..) => Err(NoSolution), - ty::Bound(..) - | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { - panic!("unexpected type `{ty:?}`") - } - // impl Copy/Clone for (T1, T2, .., Tn) where T1: Copy/Clone, T2: Copy/Clone, .. Tn: Copy/Clone ty::Tuple(tys) => Ok(ty::Binder::dummy(tys.to_vec())), @@ -272,6 +270,12 @@ where .instantiate(ecx.cx(), args) .skip_norm_wip() .map_bound(|bound| bound.types.to_vec())), + + ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) + | ty::Alias(ty::IsRigid::No, _) + | ty::Bound(..) => { + panic!("unexpected type `{ty:?}`") + } } } @@ -401,14 +405,15 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable Err(NoSolution), - ty::Bound(..) - | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { + ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) + | ty::Alias(ty::IsRigid::No, _) + | ty::Bound(..) => { panic!("unexpected type `{self_ty:?}`") } } @@ -545,7 +550,8 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_async_callable Err(NoSolution), - ty::Bound(..) - | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { + ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) + | ty::Alias(ty::IsRigid::No, _) + | ty::Bound(..) => { panic!("unexpected type `{self_ty:?}`") } } @@ -601,7 +608,8 @@ fn fn_item_to_async_callable( ]; let future_output_def_id = cx.require_projection_lang_item(SolverProjectionLangItem::FutureOutput); - let future_output_ty = Ty::new_projection(cx, future_output_def_id, [sig.output()]); + let future_output_ty = + Ty::new_projection(cx, ty::IsRigid::No, future_output_def_id, [sig.output()]); Ok(( bound_sig.rebind(AsyncCallableRelevantTypes { tupled_inputs_ty: Ty::new_tup(cx, sig.inputs().as_slice()), @@ -650,6 +658,7 @@ fn coroutine_closure_to_ambiguous_coroutine( cx.require_projection_lang_item(SolverProjectionLangItem::AsyncFnKindUpvars); let tupled_upvars_ty = Ty::new_projection( cx, + ty::IsRigid::No, upvars_projection_def_id, [ I::GenericArg::from(args.kind_ty()), @@ -739,15 +748,16 @@ pub(in crate::solve) fn extract_fn_def_from_const_callable( | ty::Never | ty::Tuple(_) | ty::Pat(_, _) - | ty::Alias(_) + | ty::Alias(ty::IsRigid::Yes, _) | ty::Param(_) | ty::Placeholder(..) | ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) | ty::Error(_) | ty::UnsafeBinder(_) => return Err(NoSolution), - ty::Bound(..) - | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { + ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) + | ty::Alias(ty::IsRigid::No, _) + | ty::Bound(..) => { panic!("unexpected type `{self_ty:?}`") } } @@ -1035,7 +1045,8 @@ where } fn try_fold_ty(&mut self, ty: I::Ty) -> Result { - if let ty::Alias(alias_ty @ ty::AliasTy { kind: ty::Projection { .. }, .. }) = ty.kind() + if let ty::Alias(_is_rigid, alias_ty @ ty::AliasTy { kind: ty::Projection { .. }, .. }) = + ty.kind() && let Some(term) = self.try_eagerly_replace_alias(alias_ty.into())? { Ok(term.expect_ty()) 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 75ba3285e13f2..0d1753063f162 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -117,7 +117,7 @@ where .skip_norm_wip(), ) }), - ); + )?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }, )); @@ -169,7 +169,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 +183,7 @@ where .skip_norm_wip(), ) }); - ecx.add_goals(GoalSource::ImplWhereBound, const_conditions); + ecx.add_goals(GoalSource::ImplWhereBound, const_conditions)?; then(ecx, certainty) }) @@ -235,8 +235,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) }) } @@ -271,8 +271,8 @@ where ), ) }), - ); - }); + ) + })?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) @@ -425,7 +425,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 e1713df023680..7bad0be49bfd0 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, 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; @@ -518,7 +519,7 @@ where // so we only canonicalize the lookup table and ignore // duplicate entries. let opaque_types = self.delegate.clone_opaque_types_lookup_table(); - let (goal, opaque_types) = eager_resolve_vars(self.delegate, (goal, opaque_types)); + let (goal, opaque_types) = eager_resolve_vars(&**self.delegate, (goal, opaque_types)); let typing_mode = self.typing_mode(); let step_kind = self.step_kind_for_source(source); @@ -1033,11 +1034,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, + ty::Unnormalized::new_wip(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))] @@ -1045,10 +1054,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 { @@ -1211,7 +1221,7 @@ where param_env: I::ParamEnv, lhs: T, rhs: T, - ) -> Result<(), NoSolution> { + ) -> Result<(), NoSolutionOrRerunNonErased> { self.relate(param_env, lhs, ty::Variance::Invariant, rhs) } @@ -1227,7 +1237,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() { @@ -1252,7 +1262,7 @@ where }; let identity_args = self.fresh_args_for_item(def_id); let rigid_ctor = alias.with_args(cx, identity_args); - let ctor_term = rigid_ctor.to_term(cx); + let ctor_term = rigid_ctor.to_term(cx, ty::IsRigid::Yes); let obligations = self.delegate.eq_structurally_relating_aliases( param_env, term, @@ -1262,7 +1272,7 @@ where debug_assert!(obligations.is_empty()); self.relate(param_env, alias, variance, rigid_ctor) } else { - Err(NoSolution) + Err(NoSolutionOrRerunNonErased::NoSolution(NoSolution)) } } @@ -1292,7 +1302,7 @@ where param_env: I::ParamEnv, sub: T, sup: T, - ) -> Result<(), NoSolution> { + ) -> Result<(), NoSolutionOrRerunNonErased> { self.relate(param_env, sub, ty::Variance::Covariant, sup) } @@ -1303,7 +1313,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() { @@ -1314,7 +1324,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(()) } @@ -1455,7 +1465,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, @@ -1464,7 +1474,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. @@ -1489,7 +1500,7 @@ where ) -> QueryResultOrRerunNonErased { match self.evaluate_const(goal.param_env, uv)? { Some(evaluated) => { - self.instantiate_normalizes_to_term(goal, evaluated.into()); + self.instantiate_normalizes_to_term(goal, evaluated.into())?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } None if self.cx().features().generic_const_args() => { @@ -1659,7 +1670,7 @@ where let external_constraints = self.compute_external_query_constraints(certainty, normalization_nested_goals); let (var_values, mut external_constraints) = - eager_resolve_vars(self.delegate, (self.var_values, external_constraints)); + eager_resolve_vars(&**self.delegate, (self.var_values, external_constraints)); // Remove any trivial or duplicated region constraints once we've resolved regions let mut unique = HashSet::default(); @@ -1745,112 +1756,43 @@ 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() - } + value: ty::Unnormalized, + ) -> Result { + let value = self.delegate.resolve_vars_if_possible(value.skip_normalization()); - 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 - } - } + if !self.cx().renormalize_rigid_aliases() && !value.has_non_rigid_aliases() { + return Ok(value); } - } - 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), - } - } + // 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_term_infer_of_kind(alias_term); + let pred = ty::PredicateKind::AliasRelate( + alias_term, + 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_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) } } @@ -1885,7 +1827,7 @@ pub(super) fn evaluate_root_goal_for_proof_tree, origin_span: I::Span, ) -> (Result, NoSolution>, inspect::GoalEvaluation) { let opaque_types = delegate.clone_opaque_types_lookup_table(); - let (goal, opaque_types) = eager_resolve_vars(delegate, (goal, opaque_types)); + let (goal, opaque_types) = eager_resolve_vars(&**delegate, (goal, opaque_types)); let typing_mode = delegate.typing_mode_raw().assert_not_erased(); let (orig_values, canonical_goal) = diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 973cf5889b04c..80908c0a55060 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -24,7 +24,7 @@ mod trait_goals; use derive_where::derive_where; use rustc_type_ir::inherent::*; pub use rustc_type_ir::solve::*; -use rustc_type_ir::{self as ty, Interner, TyVid, TypingMode}; +use rustc_type_ir::{self as ty, Interner, TyVid}; use tracing::instrument; pub use self::eval_ctxt::{ @@ -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), @@ -196,7 +196,18 @@ where Goal { param_env, predicate: ct }: Goal, ) -> QueryResultOrRerunNonErased { match ct.kind() { - ty::ConstKind::Unevaluated(uv) => { + ty::ConstKind::Unevaluated(ty::IsRigid::Yes, _) + | ty::ConstKind::Placeholder(_) + | ty::ConstKind::Value(_) + | ty::ConstKind::Error(_) => { + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + } + + ty::ConstKind::Infer(_) => { + self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + } + + ty::ConstKind::Unevaluated(ty::IsRigid::No, uv) => { // We never return `NoSolution` here as `evaluate_const` emits an // error itself when failing to evaluate, so emitting an additional fulfillment // error in that case is unnecessary noise. This may change in the future once @@ -211,12 +222,7 @@ where self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } } - ty::ConstKind::Infer(_) => { - self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) - } - ty::ConstKind::Placeholder(_) | ty::ConstKind::Value(_) | ty::ConstKind::Error(_) => { - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - } + // We can freely ICE here as: // - `Param` gets replaced with a placeholder during canonicalization // - `Bound` cannot exist as we don't have a binder around the self Type @@ -246,7 +252,12 @@ where .evaluate_added_goals_and_make_canonical_response(Certainty::Yes) .map_err(Into::into); } - ty::ConstKind::Unevaluated(uv) => uv.type_of(self.cx()).skip_norm_wip(), + ty::ConstKind::Unevaluated(ty::IsRigid::Yes, uv) => { + uv.type_of(self.cx()).skip_norm_wip() + } + ty::ConstKind::Unevaluated(ty::IsRigid::No, _) => unimplemented!( + "non-rigid unevaluated constant for compute_const_arg_has_type_goal: {ct:?}" + ), ty::ConstKind::Expr(_) => unimplemented!( "`feature(generic_const_exprs)` is not supported in the new trait solver" ), @@ -366,6 +377,10 @@ where param_env: I::ParamEnv, term: I::Term, ) -> Result { + if !self.cx().renormalize_rigid_aliases() && !term.is_non_rigid_alias() { + return Ok(term); + } + if let Some(_) = term.to_alias_term() { let normalized_term = self.next_term_infer_of_kind(term); let alias_relate_goal = Goal::new( @@ -379,31 +394,13 @@ 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 { Ok(term) } } - - fn opaque_type_is_rigid(&self, def_id: I::OpaqueTyId) -> bool { - match self - .typing_mode() - // Caller should handle erased mode - .assert_not_erased() - { - // Opaques are never rigid outside of analysis mode. - TypingMode::Coherence | TypingMode::PostAnalysis | TypingMode::Codegen => false, - // During analysis, opaques are rigid unless they may be defined by - // the current body. - TypingMode::Typeck { defining_opaque_types_and_generators: non_rigid_opaques } - | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: non_rigid_opaques } - | TypingMode::PostBorrowck { defined_opaque_types: non_rigid_opaques } => { - !def_id.as_local().is_some_and(|def_id| non_rigid_opaques.contains(&def_id.into())) - } - } - } } /// The result of evaluating a goal. 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 22d8634c2ff89..28f603d8f3b74 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,20 @@ where .iter_instantiated(cx, free_alias.args) .map(Unnormalized::skip_norm_wip) .map(|pred| goal.with(cx, pred)), - ); + )?; let actual = match free_alias.kind { 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); + 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); + 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, @@ -49,7 +52,7 @@ where kind => panic!("expected free alias, found {kind:?}"), }; - self.instantiate_normalizes_to_term(goal, actual); + self.instantiate_normalizes_to_term(goal, actual)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } 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 9864b92ad57df..34d92935eea93 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 @@ -51,17 +51,19 @@ where .iter_instantiated(cx, inherent_args) .map(Unnormalized::skip_norm_wip) .map(|pred| goal.with(cx, pred)), - ); + )?; let normalized: I::Term = match inherent.kind { 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); + 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); + 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 @@ -74,7 +76,7 @@ where kind => panic!("expected inherent alias, found {kind:?}"), }; - self.instantiate_normalizes_to_term(goal, normalized); + self.instantiate_normalizes_to_term(goal, normalized)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } 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 b85a19045aef2..52f7a8c81684c 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 @@ -141,7 +141,7 @@ where &mut self, goal: Goal>, term: I::Term, - ) { + ) -> Result<(), NoSolutionOrRerunNonErased> { if let Some(ct) = term.as_const() { let cx = self.cx(); let alias = goal.predicate.alias; @@ -149,10 +149,11 @@ where self.add_goal( GoalSource::Misc, goal.with(cx, ty::ClauseKind::ConstArgHasType(ct, expected_ty)), - ); + )?; } self.eq(goal.param_env, goal.predicate.term, term) .expect("expected goal term to be fully unconstrained"); + Ok(()) } /// Unlike `instantiate_normalizes_to_term` this instantiates the expected term @@ -162,8 +163,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( + goal.param_env, + term.to_term(self.cx(), ty::IsRigid::Yes), + ty::Invariant, + goal.predicate.term, + ) + .expect("expected goal term to be fully unconstrained"); } } @@ -222,7 +228,7 @@ where let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred); ecx.eq(goal.param_env, goal.predicate.alias, assumption_projection_pred.projection_term)?; - ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term); + ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term)?; // Add GAT where clauses from the trait's definition // FIXME: We don't need these, since these are the type's own WF obligations. @@ -232,7 +238,7 @@ where .iter_instantiated(cx, goal.predicate.alias.args) .map(Unnormalized::skip_norm_wip) .map(|pred| goal.with(cx, pred)), - ); + )?; then(ecx) } @@ -298,7 +304,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 @@ -315,7 +321,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 { @@ -323,7 +329,7 @@ where ty::AliasTermKind::ProjectionConst { .. } => Const::new_error(cx, guar).into(), kind => panic!("expected projection, found {kind:?}"), }; - ecx.instantiate_normalizes_to_term(goal, error_term); + ecx.instantiate_normalizes_to_term(goal, error_term)?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }; @@ -347,7 +353,7 @@ where ecx.add_goal( GoalSource::Misc, goal.with(cx, PredicateKind::Ambiguous), - ); + )?; return ecx .evaluate_added_goals_and_make_canonical_response( Certainty::Yes, @@ -397,7 +403,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); @@ -437,18 +443,18 @@ where // Finally we construct the actual value of the associated type. let term = match goal.predicate.alias.kind { - 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); + 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()) - .instantiate(cx, target_args) - .skip_norm_wip() - .into() + let c = + cx.const_of_item(target_item_def_id.into()).instantiate(cx, target_args); + let c = ecx.normalize(GoalSource::Misc, goal.param_env, c)?; + c.into() } ty::AliasTermKind::ProjectionConst { .. } => { let uv = ty::UnevaluatedConst::new( @@ -463,7 +469,7 @@ where kind => panic!("expected projection, found {kind:?}"), }; - ecx.instantiate_normalizes_to_term(goal, term); + ecx.instantiate_normalizes_to_term(goal, term)?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes).map_err(Into::into) }) } @@ -483,7 +489,7 @@ where }; ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { - ecx.instantiate_normalizes_to_term(goal, error_term); + ecx.instantiate_normalizes_to_term(goal, error_term)?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -693,7 +699,7 @@ where ); ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { - ecx.instantiate_normalizes_to_term(goal, upvars_ty.into()); + ecx.instantiate_normalizes_to_term(goal, upvars_ty.into())?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -746,7 +752,7 @@ where .skip_norm_wip() } - ty::Alias(_) | ty::Param(_) | ty::Placeholder(..) => { + ty::Alias(ty::IsRigid::Yes, _) | ty::Param(_) | ty::Placeholder(..) => { // This is the "fallback impl" for type parameters, unnormalizable projections // and opaque types: If the `self_ty` is `Sized`, then the metadata is `()`. // FIXME(ptr_metadata): This impl overlaps with the other impls and shouldn't @@ -758,8 +764,8 @@ 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.instantiate_normalizes_to_term(goal, Ty::new_unit(cx).into()); + 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) }); @@ -785,6 +791,7 @@ where None => Ty::new_unit(cx), Some(tail_ty) => Ty::new_projection( cx, + ty::IsRigid::No, metadata_def_id, [tail_ty.instantiate(cx, args).skip_norm_wip()], ), @@ -793,7 +800,9 @@ where ty::Tuple(elements) => match elements.last() { None => Ty::new_unit(cx), - Some(tail_ty) => Ty::new_projection(cx, metadata_def_id, [tail_ty]), + Some(tail_ty) => { + Ty::new_projection(cx, ty::IsRigid::No, metadata_def_id, [tail_ty]) + } }, ty::UnsafeBinder(_) => { @@ -802,6 +811,7 @@ where } ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) + | ty::Alias(ty::IsRigid::No, _) | ty::Bound(..) => panic!( "unexpected self ty `{:?}` when normalizing `::Metadata`", goal.predicate.self_ty() @@ -809,7 +819,7 @@ where }; ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { - ecx.instantiate_normalizes_to_term(goal, metadata_ty.into()); + ecx.instantiate_normalizes_to_term(goal, metadata_ty.into())?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -836,7 +846,13 @@ where CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, ty::ProjectionPredicate { - projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.alias.kind, [self_ty]), + projection_term: ty::AliasTerm::new( + ecx.cx(), + cx.alias_term_kind_from_def_id( + goal.predicate.alias.expect_projection_def_id().into(), + ), + [self_ty], + ), term, } .upcast(cx), @@ -868,7 +884,13 @@ where CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, ty::ProjectionPredicate { - projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.alias.kind, [self_ty]), + projection_term: ty::AliasTerm::new( + ecx.cx(), + cx.alias_term_kind_from_def_id( + goal.predicate.alias.expect_projection_def_id().into(), + ), + [self_ty], + ), term, } .upcast(cx), @@ -917,7 +939,7 @@ where ); let yield_ty = args.as_coroutine().yield_ty(); ecx.eq(goal.param_env, wrapped_expected_ty, yield_ty)?; - ecx.instantiate_normalizes_to_term(goal, expected_ty.into()); + ecx.instantiate_normalizes_to_term(goal, expected_ty.into())?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -1014,7 +1036,7 @@ where // Given an alias, parameter, or placeholder we add an impl candidate normalizing to a rigid // alias. In case there's a where-bound further constraining this alias it is preferred over // this impl candidate anyways. It's still a bit scuffed. - ty::Alias(_) | ty::Param(_) | ty::Placeholder(..) => { + ty::Alias(ty::IsRigid::Yes, _) | ty::Param(_) | ty::Placeholder(..) => { return ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { ecx.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) @@ -1022,6 +1044,7 @@ where } ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) + | ty::Alias(ty::IsRigid::No, _) | ty::Bound(..) => panic!( "unexpected self ty `{:?}` when normalizing `::Discriminant`", goal.predicate.self_ty() @@ -1029,7 +1052,7 @@ where }; ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { - ecx.instantiate_normalizes_to_term(goal, discriminant_ty.into()); + ecx.instantiate_normalizes_to_term(goal, discriminant_ty.into())?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -1074,7 +1097,7 @@ where _ => panic!("unexpected associated type {:?} in `Field`", goal.predicate), }; ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { - ecx.instantiate_normalizes_to_term(goal, ty.into()); + ecx.instantiate_normalizes_to_term(goal, ty.into())?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) } @@ -1092,7 +1115,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. @@ -1117,7 +1140,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 2e56e98f8c9be..a83f44f1fe6ae 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) } @@ -88,8 +88,9 @@ where TypingMode::PostTypeckUntilBorrowck { .. } => { let actual = cx .type_of_opaque_hir_typeck(def_id) - .instantiate(cx, opaque_ty.args) - .skip_norm_wip(); + .instantiate(cx, opaque_ty.args); + 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, @@ -108,7 +109,7 @@ where normalized_args, goal.param_env, expected, - ); + )?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) .map_err(Into::into) } @@ -123,8 +124,8 @@ where .map_err(Into::into); }; - let actual = - cx.type_of(def_id.into()).instantiate(cx, opaque_ty.args).skip_norm_wip(); + let actual = cx.type_of(def_id.into()).instantiate(cx, opaque_ty.args); + 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: @@ -138,8 +139,8 @@ where } TypingMode::PostAnalysis | TypingMode::Codegen => { // 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 = cx.type_of(def_id.into()).instantiate(cx, opaque_ty.args); + 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..b980ecbac333a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/project_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals.rs @@ -16,7 +16,7 @@ where goal: Goal>, ) -> QueryResultOrRerunNonErased { let cx = self.cx(); - let projection_term = goal.predicate.projection_term.to_term(cx); + let projection_term = goal.predicate.projection_term.to_term(cx, ty::IsRigid::No); let goal = goal.with( cx, ty::PredicateKind::AliasRelate( @@ -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 a8c5b95415621..79e0af72710fb 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) }) @@ -235,15 +235,15 @@ where // when merging candidates anyways. // // See tests/ui/impl-trait/auto-trait-leakage/avoid-query-cycle-via-item-bound.rs. - if let ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }) = + if let ty::Alias(is_rigid, ty::AliasTy { kind: ty::Opaque { def_id }, .. }) = goal.predicate.self_ty().kind() { + debug_assert!(is_rigid == ty::IsRigid::Yes); if ecx.opaque_accesses.might_rerun() { ecx.opaque_accesses.rerun_always(RerunReason::AutoTraitLeakage)?; return Err(NoSolution.into()); } - debug_assert!(ecx.opaque_type_is_rigid(def_id)); for item_bound in cx.item_self_bounds(def_id.into()).skip_binder() { if item_bound .as_trait_clause() @@ -287,7 +287,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) }) } @@ -737,13 +737,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 @@ -784,7 +784,7 @@ where [ty], ), ), - ); + )?; } ty::Bound(..) @@ -891,14 +891,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()), }, - ); + )?; // FIXME(field_projections): This function does some questionable incomplete stuff by // returning `Err(NoSolution)` on ambiguity. ecx.try_evaluate_added_goals()? == Certainty::Yes @@ -1018,7 +1018,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( @@ -1031,10 +1031,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) }) } @@ -1154,7 +1154,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) }) @@ -1235,7 +1235,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)) } @@ -1287,14 +1287,15 @@ where ty::Dynamic(..) | ty::Param(..) | ty::Foreign(..) - | ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Free { .. } | ty::Inherent { .. }, - .. - }) + | ty::Alias( + ty::IsRigid::Yes, + ty::AliasTy { + kind: ty::Projection { .. } | ty::Free { .. } | ty::Inherent { .. }, + .. + }, + ) | ty::Placeholder(..) => Some(Err(NoSolution.into())), - ty::Infer(_) | ty::Bound(_, _) => panic!("unexpected type `{self_ty:?}`"), - // Coroutines have one special built-in candidate, `Unpin`, which // takes precedence over the structural auto trait candidate being // assembled. @@ -1317,7 +1318,7 @@ where // okay to consider auto traits because that'll reveal its hidden type. For // non-opaque aliases, we will not assemble any candidates since there's no way // to further look into its type. - ty::Alias(..) => None, + ty::Alias(ty::IsRigid::Yes, ty::AliasTy { kind: ty::Opaque { .. }, .. }) => None, // For rigid types, any possible implementation that could apply to // the type (even if after unification and processing nested goals @@ -1347,6 +1348,10 @@ where | ty::Adt(_, _) | ty::UnsafeBinder(_) => check_impls(), ty::Error(_) => None, + + ty::Infer(_) | ty::Alias(ty::IsRigid::No, _) | ty::Bound(_, _) => { + panic!("unexpected type `{self_ty:?}`") + } } } @@ -1375,7 +1380,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_passes/src/check_export.rs b/compiler/rustc_passes/src/check_export.rs index fa3042277b409..39ca07eb824c1 100644 --- a/compiler/rustc_passes/src/check_export.rs +++ b/compiler/rustc_passes/src/check_export.rs @@ -312,7 +312,7 @@ impl<'tcx, 'a> TypeVisitor> for ExportableItemsChecker<'tcx, 'a> { | ty::CoroutineWitness(_, _) | ty::Never | ty::UnsafeBinder(_) - | ty::Alias(ty::AliasTy { kind: ty::AliasTyKind::Opaque { .. }, .. }) => { + | ty::Alias(_, ty::AliasTy { kind: ty::AliasTyKind::Opaque { .. }, .. }) => { return ControlFlow::Break(ty); } diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index b5491de7905bc..d2822f9ad62a6 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -126,7 +126,8 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { #[inline] pub fn reveal_opaque_ty(&self, ty: Ty<'tcx>) -> RevealedTy<'tcx> { fn reveal_inner<'tcx>(cx: &RustcPatCtxt<'_, 'tcx>, ty: Ty<'tcx>) -> RevealedTy<'tcx> { - let ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) = *ty.kind() + debug_assert!(!cx.tcx.next_trait_solver_globally()); + let ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) = *ty.kind() else { bug!() }; @@ -138,7 +139,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { } RevealedTy(ty) } - if let ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }) = ty.kind() { + if let ty::Alias(ty::IsRigid::No, ty::AliasTy { kind: ty::Opaque { .. }, .. }) = ty.kind() { reveal_inner(self, ty) } else { RevealedTy(ty) @@ -426,7 +427,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { | ty::CoroutineClosure(..) | ty::Coroutine(_, _) | ty::UnsafeBinder(_) - | ty::Alias(_) + | ty::Alias(_, _) | ty::Param(_) | ty::Error(_) => ConstructorSet::Unlistable, ty::CoroutineWitness(_, _) | ty::Bound(_, _) | ty::Placeholder(_) | ty::Infer(_) => { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 1cd1101db090d..6f09e53f0a8e7 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -215,6 +215,7 @@ where } } ty::Alias( + _, data @ ty::AliasTy { kind: kind @ (ty::Inherent { def_id } @@ -274,7 +275,7 @@ where try_visit!(self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref)); } } - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }) => { // Skip repeated `Opaque`s to avoid infinite recursion. if self.visited_tys.insert(ty) { // The intent is to treat `impl Trait1 + Trait2` identically to diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index 4218c21f508d3..49957642924ec 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -483,7 +483,7 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { ty::Tuple(fields) => TyKind::RigidTy(RigidTy::Tuple( fields.iter().map(|ty| ty.stable(tables, cx)).collect(), )), - ty::Alias(alias_ty) => { + ty::Alias(_is_rigid, alias_ty) => { TyKind::Alias(alias_ty.kind.stable(tables, cx), alias_ty.stable(tables, cx)) } ty::Param(param_ty) => TyKind::Param(param_ty.stable(tables, cx)), @@ -548,7 +548,7 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { } } ty::ConstKind::Param(param) => crate::ty::TyConstKind::Param(param.stable(tables, cx)), - ty::ConstKind::Unevaluated(uv) => { + ty::ConstKind::Unevaluated(_is_rigid, uv) => { let Some(def_id) = uv.kind.opt_def_id() else { // FIXME: implement (both AliasTy and UnevaluatedConst will be needing this soon) panic!( 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..deff4241d9097 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 @@ -252,9 +252,12 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc ); let term = tcx.normalize_erasing_regions( ty::TypingEnv::fully_monomorphized(), - Unnormalized::new_wip(projection_term.to_term(tcx)), + Unnormalized::new_wip(projection_term.to_term(tcx, ty::IsRigid::No)), + ); + debug!( + "Projection {:?} -> {term}", + projection_term.to_term(tcx, ty::IsRigid::No) ); - debug!("Projection {:?} -> {term}", projection_term.to_term(tcx),); ty::ExistentialPredicate::Projection( ty::ExistentialProjection::erase_self_ty( tcx, @@ -506,7 +509,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_session/src/options.rs b/compiler/rustc_session/src/options.rs index 0582791dad005..ad4d73dfe51ff 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2620,6 +2620,8 @@ options! { remark_dir: Option = (None, parse_opt_pathbuf, [UNTRACKED], "directory into which to write optimization remarks (if not specified, they will be \ written to standard error output)"), + renormalize_rigid_aliases: bool = (false, parse_bool, [TRACKED], + "do not skip rigid aliases in normalization for internal debugging"), retpoline: bool = (false, parse_bool, [TRACKED] { TARGET_MODIFIER: Retpoline }, "enables retpoline-indirect-branches and retpoline-indirect-calls target features (default: no)"), retpoline_external_thunk: bool = (false, parse_bool, [TRACKED] { TARGET_MODIFIER: RetpolineExternalThunk }, diff --git a/compiler/rustc_symbol_mangling/src/export.rs b/compiler/rustc_symbol_mangling/src/export.rs index ffb00632ea4f4..9f9c30abe2c1b 100644 --- a/compiler/rustc_symbol_mangling/src/export.rs +++ b/compiler/rustc_symbol_mangling/src/export.rs @@ -118,7 +118,7 @@ impl<'tcx> AbiStableHash<'tcx> for Ty<'tcx> { | ty::CoroutineWitness(_, _) | ty::Never | ty::Tuple(_) - | ty::Alias(_) + | ty::Alias(_, _) | ty::Param(_) | ty::Bound(_, _) | ty::Placeholder(_) diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index c13300a735c3c..5f076040138e8 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -243,11 +243,12 @@ impl<'tcx> Printer<'tcx> for LegacySymbolMangler<'tcx> { match *ty.kind() { // Print all nominal types as paths (unlike `pretty_print_type`). ty::FnDef(def_id, args) - | ty::Alias(ty::AliasTy { - kind: ty::Projection { def_id } | ty::Opaque { def_id }, - args, - .. - }) + | ty::Alias( + _, + ty::AliasTy { + kind: ty::Projection { def_id } | ty::Opaque { def_id }, args, .. + }, + ) | ty::Closure(def_id, args) | ty::CoroutineClosure(def_id, args) | ty::Coroutine(def_id, args) => self.print_def_path(def_id, args), @@ -269,7 +270,7 @@ impl<'tcx> Printer<'tcx> for LegacySymbolMangler<'tcx> { Ok(()) } - ty::Alias(ty::AliasTy { kind: ty::Inherent { .. }, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Inherent { .. }, .. }) => { panic!("unexpected inherent projection") } diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index c6624a7820559..044f24ac4de0e 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -548,7 +548,7 @@ impl<'tcx> Printer<'tcx> for V0SymbolMangler<'tcx> { // We may still encounter projections here due to the printing // logic sometimes passing identity-substituted impl headers. - ty::Alias(ty::AliasTy { kind: ty::Projection { def_id }, args, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Projection { def_id }, args, .. }) => { self.print_def_path(def_id, args)?; } @@ -692,7 +692,7 @@ impl<'tcx> Printer<'tcx> for V0SymbolMangler<'tcx> { // We may still encounter unevaluated consts due to the printing // logic sometimes passing identity-substituted impl headers. - ty::ConstKind::Unevaluated(ty::UnevaluatedConst { kind, args, .. }) => match kind { + ty::ConstKind::Unevaluated(_, ty::UnevaluatedConst { kind, args, .. }) => match kind { ty::UnevaluatedConstKind::Projection { def_id } | ty::UnevaluatedConstKind::Inherent { def_id } | ty::UnevaluatedConstKind::Free { def_id } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index ad9ac989c6c7f..1e25e00de7d89 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -209,8 +209,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option> { let (def_id, args) = match *ty.kind() { - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => (def_id, args), - ty::Alias(ty::AliasTy { kind, args, .. }) + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => (def_id, args), + ty::Alias(_, ty::AliasTy { kind, args, .. }) if self.tcx.is_impl_trait_in_trait(kind.def_id()) => { (kind.def_id(), args) @@ -281,10 +281,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, ) { let (alias, &def_id, concrete) = match (expected.kind(), found.kind()) { - (ty::Alias(proj @ ty::AliasTy { kind: ty::Projection { def_id }, .. }), _) => { + (ty::Alias(_, proj @ ty::AliasTy { kind: ty::Projection { def_id }, .. }), _) => { (proj, def_id, found) } - (_, ty::Alias(proj @ ty::AliasTy { kind: ty::Projection { def_id }, .. })) => { + (_, ty::Alias(_, proj @ ty::AliasTy { kind: ty::Projection { def_id }, .. })) => { (proj, def_id, expected) } _ => return, @@ -348,7 +348,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { "the associated type `{}` is defined as `{}` in the implementation, \ but the where-bound `{}` shadows this definition\n\ see issue #152409 for more information", - self.ty_to_string(tcx.mk_ty_from_kind(ty::Alias(*alias))), + self.ty_to_string(alias.to_ty(tcx, ty::IsRigid::No)), self.ty_to_string(concrete), self.ty_to_string(alias.self_ty()) )); @@ -1705,7 +1705,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && values.expected.sort_string(self.tcx) != values.found.sort_string(self.tcx); let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) { - (true, ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. })) => { + (true, ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. })) => { let sm = self.tcx.sess.source_map(); let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo()); DiagStyledString::normal(format!( @@ -1715,9 +1715,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { pos.col.to_usize() + 1, )) } - (true, &ty::Alias(ty::AliasTy { kind: ty::Projection { def_id }, .. })) - if self.tcx.is_impl_trait_in_trait(def_id) => - { + ( + true, + &ty::Alias(_, ty::AliasTy { kind: ty::Projection { def_id }, .. }), + ) if self.tcx.is_impl_trait_in_trait(def_id) => { let sm = self.tcx.sess.source_map(); let pos = sm.lookup_char_pos(self.tcx.def_span(def_id).lo()); DiagStyledString::normal(format!( @@ -2553,7 +2554,7 @@ impl TyCategory { pub fn from_ty(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Self, DefId)> { match *ty.kind() { ty::Closure(def_id, _) => Some((Self::Closure, def_id)), - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }) => { let kind = if tcx.ty_is_opaque_future(ty) { Self::OpaqueFuture } else { Self::Opaque }; Some((kind, def_id)) diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs index 2aea9e5bcf369..333f6f01c0ef1 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs @@ -1060,7 +1060,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { GenericArgKind::Type(ty) => { if matches!( ty.kind(), - ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }) + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(..) diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs index dfa0d4a3bfd48..2d48b41bcb361 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs @@ -162,7 +162,12 @@ pub fn suggest_new_region_bound( TyKind::OpaqueDef(opaque) => { // Get the identity type for this RPIT let did = opaque.def_id.to_def_id(); - let ty = Ty::new_opaque(tcx, did, ty::GenericArgs::identity_for_item(tcx, did)); + let ty = Ty::new_opaque( + tcx, + ty::IsRigid::No, + did, + ty::GenericArgs::identity_for_item(tcx, did), + ); if let Some(span) = opaque.bounds.iter().find_map(|arg| match arg { GenericBound::Outlives(Lifetime { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index 236b5055dce80..de838b5846985 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -46,8 +46,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ); } ( - ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }), - ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }), + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }), + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }), ) => { // Issue #63167 diag.note("distinct uses of `impl Trait` result in different opaque types"); @@ -89,24 +89,28 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { ); } ( - ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. }, - .. - }), - ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. }, - .. - }), + ty::Alias( + _, + ty::AliasTy { + kind: ty::Projection { .. } | ty::Inherent { .. }, .. + }, + ), + ty::Alias( + _, + ty::AliasTy { + kind: ty::Projection { .. } | ty::Inherent { .. }, .. + }, + ), ) => { diag.note("an associated type was expected, but a different one was found"); } // FIXME(inherent_associated_types): Extend this to support `ty::Inherent`, too. ( ty::Param(p), - ty::Alias(proj @ ty::AliasTy { kind: ty::Projection { def_id }, .. }), + ty::Alias(_, proj @ ty::AliasTy { kind: ty::Projection { def_id }, .. }), ) | ( - ty::Alias(proj @ ty::AliasTy { kind: ty::Projection { def_id }, .. }), + ty::Alias(_, proj @ ty::AliasTy { kind: ty::Projection { def_id }, .. }), ty::Param(p), ) if !tcx.is_impl_trait_in_trait(def_id) && let Some(generics) = body_generics => @@ -229,10 +233,10 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } ( ty::Param(p), - ty::Dynamic(..) | ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }), + ty::Dynamic(..) | ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }), ) | ( - ty::Dynamic(..) | ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }), + ty::Dynamic(..) | ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }), ty::Param(p), ) => { if let Some(generics) = body_generics { @@ -308,6 +312,7 @@ impl Trait for X { } ( ty::Alias( + _, proj_ty @ ty::AliasTy { kind: ty::Projection { def_id } | ty::Inherent { def_id }, .. @@ -328,6 +333,7 @@ impl Trait for X { ( _, ty::Alias( + _, proj_ty @ ty::AliasTy { kind: ty::Projection { def_id } | ty::Inherent { def_id }, .. @@ -368,9 +374,10 @@ impl Trait for X { } ( ty::Dynamic(t, _), - ty::Alias(ty::AliasTy { - kind: ty::Opaque { def_id: opaque_def_id }, .. - }), + ty::Alias( + _, + ty::AliasTy { kind: ty::Opaque { def_id: opaque_def_id }, .. }, + ), ) if let Some(def_id) = t.principal_def_id() && tcx .explicit_item_self_bounds(opaque_def_id) @@ -429,8 +436,8 @@ impl Trait for X { )); } } - (_, ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. })) - | (ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }), _) => { + (_, ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. })) + | (ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }), _) => { if let Some(body_owner_def_id) = body_owner_def_id && def_id.is_local() && matches!( @@ -822,7 +829,7 @@ fn foo(&self) -> Self::T { String::new() } let tcx = self.tcx; let assoc = tcx.associated_item(proj_ty.kind.def_id()); - if let ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }) = + if let ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }) = *proj_ty.self_ty().kind() { let opaque_local_def_id = def_id.as_local(); @@ -873,9 +880,10 @@ fn foo(&self) -> Self::T { String::new() } .filter_map(|item| { let method = tcx.fn_sig(item.def_id).instantiate_identity().skip_norm_wip(); match *method.output().skip_binder().kind() { - ty::Alias(ty::AliasTy { - kind: ty::Projection { def_id: item_def_id }, .. - }) if item_def_id == proj_ty_item_def_id => Some(( + ty::Alias( + _, + ty::AliasTy { kind: ty::Projection { def_id: item_def_id }, .. }, + ) if item_def_id == proj_ty_item_def_id => Some(( tcx.def_span(item.def_id), format!("consider calling `{}`", tcx.def_path_str(item.def_id)), )), diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index f6ef59918af0c..7e706a9838306 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -1278,7 +1278,12 @@ pub fn unexpected_hidden_region_diagnostic<'a, 'tcx>( let tcx = infcx.tcx; let mut err = infcx.dcx().create_err(diagnostics::OpaqueCapturesLifetime { span, - opaque_ty: Ty::new_opaque(tcx, opaque_ty_key.def_id.to_def_id(), opaque_ty_key.args), + opaque_ty: Ty::new_opaque( + tcx, + ty::IsRigid::No, + opaque_ty_key.def_id.to_def_id(), + opaque_ty_key.args, + ), opaque_ty_span: tcx.def_span(opaque_ty_key.def_id), }); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs index 516164bb2e58e..88b51a3603fec 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs @@ -769,20 +769,22 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { StatementAsExpression::CorrectType } ( - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id: last_def_id }, .. }), - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id: exp_def_id }, .. }), + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: last_def_id }, .. }), + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: exp_def_id }, .. }), ) if last_def_id == exp_def_id => StatementAsExpression::CorrectType, ( - ty::Alias(ty::AliasTy { - kind: ty::Opaque { def_id: last_def_id }, - args: last_bounds, - .. - }), - ty::Alias(ty::AliasTy { - kind: ty::Opaque { def_id: exp_def_id }, - args: exp_bounds, - .. - }), + ty::Alias( + _, + ty::AliasTy { + kind: ty::Opaque { def_id: last_def_id }, args: last_bounds, .. + }, + ), + ty::Alias( + _, + ty::AliasTy { + kind: ty::Opaque { def_id: exp_def_id }, args: exp_bounds, .. + }, + ), ) => { debug!( "both opaque, likely future {:?} {:?} {:?} {:?}", diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs index b8e8204572d82..60ae0cd644460 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs @@ -6,7 +6,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::{LangItem, lang_items}; use rustc_middle::ty::{ - AssocContainer, GenericArgsRef, Instance, Ty, TyCtxt, TypingEnv, Unnormalized, + self, AssocContainer, GenericArgsRef, Instance, Ty, TyCtxt, TypingEnv, Unnormalized, }; use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, sym}; use tracing::debug; @@ -104,7 +104,12 @@ pub fn call_kind<'tcx>( tcx.get_diagnostic_item(sym::deref_target).expect("deref method but no deref target"); let deref_target_ty = tcx.normalize_erasing_regions( typing_env, - Unnormalized::new(Ty::new_projection(tcx, deref_target_def_id, method_args)), + Unnormalized::new(Ty::new_projection( + tcx, + ty::IsRigid::No, + deref_target_def_id, + method_args, + )), ); let deref_target_span = if let Ok(Some(instance)) = Instance::try_resolve(tcx, typing_env, method_did, method_args) 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 aa414dc6fedb6..bbe657f213085 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 @@ -1612,7 +1612,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { infer::BoundRegionConversionTime::HigherRankedType, bound_predicate.rebind(data), ); - let unnormalized_term = data.projection_term.to_term(self.tcx); + let unnormalized_term = data.projection_term.to_term(self.tcx, ty::IsRigid::No); // FIXME(-Znext-solver): For diagnostic purposes, it would be nice // to deeply normalize this type. let normalized_term = ocx.normalize( @@ -1651,7 +1651,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let normalized_term = ocx.normalize( &ObligationCause::dummy(), obligation.param_env, - Unnormalized::new_wip(alias_term.to_term(self.tcx)), + Unnormalized::new_wip( + alias_term.to_term(self.tcx, ty::IsRigid::No), + ), ); if let Err(terr) = ocx.eq( @@ -1912,10 +1914,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ty::Closure(..) => Some(9), ty::Tuple(..) => Some(10), ty::Param(..) => Some(11), - ty::Alias(ty::AliasTy { kind: ty::Projection { .. }, .. }) => Some(12), - ty::Alias(ty::AliasTy { kind: ty::Inherent { .. }, .. }) => Some(13), - ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }) => Some(14), - ty::Alias(ty::AliasTy { kind: ty::Free { .. }, .. }) => Some(15), + ty::Alias(_, ty::AliasTy { kind: ty::Projection { .. }, .. }) => Some(12), + ty::Alias(_, ty::AliasTy { kind: ty::Inherent { .. }, .. }) => Some(13), + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }) => Some(14), + ty::Alias(_, ty::AliasTy { kind: ty::Free { .. }, .. }) => Some(15), ty::Never => Some(16), ty::Adt(..) => Some(17), ty::Coroutine(..) => Some(18), @@ -2140,7 +2142,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( @@ -2798,12 +2801,23 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.infcx.tcx } + // FIXME: why don't we also instantiate const and region params with infer vars + // here? Because diagnostics isn't soundness critical and no one bothers to be + // pedantic yet. fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if let ty::Param(_) = *ty.kind() { - let infcx = self.infcx; - *self.var_map.entry(ty).or_insert_with(|| infcx.next_ty_var(DUMMY_SP)) - } else { - ty.super_fold_with(self) + match ty.kind() { + ty::Param(_) => { + let infcx = self.infcx; + *self.var_map.entry(ty).or_insert_with(|| infcx.next_ty_var(DUMMY_SP)) + } + &ty::Alias(is_rigid, alias) + if is_rigid == ty::IsRigid::Yes + && ty.has_type_flags(ty::TypeFlags::HAS_TY_PARAM) => + { + let alias = alias.fold_with(self); + Ty::new_alias(self.cx(), ty::IsRigid::No, alias) + } + _ => ty.super_fold_with(self), } } } @@ -3745,7 +3759,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { match obligation.predicate.kind().skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => match ct.kind() { - ty::ConstKind::Unevaluated(uv) => { + ty::ConstKind::Unevaluated(_, uv) => { let mut err = self.dcx().struct_span_err(span, "unconstrained generic constant"); let const_span = uv.kind.def_span(self.tcx); 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 0849215c13404..e5de80b97d7dd 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -479,7 +479,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let self_ty = trait_pred.skip_binder().self_ty(); let (param_ty, projection) = match *self_ty.kind() { ty::Param(_) => (true, None), - ty::Alias(projection @ ty::AliasTy { kind: ty::Projection { .. }, .. }) => { + ty::Alias(_, projection @ ty::AliasTy { kind: ty::Projection { .. }, .. }) => { (false, Some(projection)) } _ => (false, None), @@ -1483,7 +1483,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { sig_parts.map_bound(|sig| sig.tupled_inputs_ty.tuple_fields().as_slice()), )) } - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => { self.tcx .item_self_bounds(def_id) .instantiate(self.tcx, args) @@ -4050,7 +4050,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } } - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }) => { // If the previous type is async fn, this is the future generated by the body of an async function. // Avoid printing it twice (it was already printed in the `ty::Coroutine` arm below). let is_future = tcx.ty_is_opaque_future(ty); @@ -4533,6 +4533,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let projection_ty = trait_pred.map_bound(|trait_pred| { Ty::new_projection( self.tcx, + ty::IsRigid::No, item_def_id, // Future::Output has no args [trait_pred.self_ty()], @@ -4877,7 +4878,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { .skip_binder() .projection_term .expect_ty() - .to_ty(self.tcx), + .to_ty(self.tcx, ty::IsRigid::No), found, })]; } @@ -4975,7 +4976,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Extract `::Target` assoc type and check that it is `T` && let Some(deref_target_did) = tcx.lang_items().deref_target() - && let projection = Ty::new_projection_from_args(tcx,deref_target_did, tcx.mk_args(&[ty::GenericArg::from(found_ty)])) + && let projection = Ty::new_projection_from_args(tcx,ty::IsRigid::No, deref_target_did, tcx.mk_args(&[ty::GenericArg::from(found_ty)])) && let InferOk { value: deref_target, obligations } = infcx.at(&ObligationCause::dummy(), param_env).normalize(Unnormalized::new_wip(projection)) && obligations.iter().all(|obligation| infcx.predicate_must_hold_modulo_regions(obligation)) && infcx.can_eq(param_env, deref_target, target_ty) @@ -5337,7 +5338,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let TypeError::Sorts(expected_found) = diff else { continue; }; - let &ty::Alias(ty::AliasTy { kind: kind @ ty::Projection { def_id }, .. }) = + let &ty::Alias(_, ty::AliasTy { kind: kind @ ty::Projection { def_id }, .. }) = expected_found.expected.kind() else { continue; @@ -5665,7 +5666,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } // Look for an RPITIT - let ty::Alias(alias_ty @ ty::AliasTy { kind: ty::Projection { def_id }, .. }) = + let ty::Alias(_, alias_ty @ ty::AliasTy { kind: ty::Projection { def_id }, .. }) = trait_pred.self_ty().skip_binder().kind() else { return; diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 9606efe4a3d8b..10d5202905c72 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -225,7 +225,7 @@ pub fn report_item_does_not_constrain_error<'tcx>( err.note("consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`"); err.span_note(opaque_type_span, "this opaque type is supposed to be constrained"); if let Some((key, span)) = non_defining_use { - let opaque_ty = Ty::new_opaque(tcx, key.def_id.into(), key.args); + let opaque_ty = Ty::new_opaque(tcx, ty::IsRigid::No, key.def_id.into(), key.args); err.span_note( span, format!("this use of `{opaque_ty}` does not have unique universal generic arguments"), diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index 209404de5f7ff..f907b4ba19122 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -220,7 +220,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< param_env: ty::ParamEnv<'tcx>, uv: ty::UnevaluatedConst<'tcx>, ) -> Option> { - let ct = ty::Const::new_unevaluated(self.tcx, uv); + let ct = ty::Const::new_unevaluated(self.tcx, ty::IsRigid::No, uv); match crate::traits::try_evaluate_const(&self.0, ct, param_env) { Ok(ct) => Some(ct), diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 4b80d22d6bb49..6bfb7f59d513d 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -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; @@ -182,9 +182,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/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 0ce4e9e71fc9f..c55876633a440 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -34,7 +34,7 @@ pub(super) fn fulfillment_error_for_no_solution<'tcx>( } ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, expected_ty)) => { let ct_ty = match ct.kind() { - ty::ConstKind::Unevaluated(uv) => uv.type_of(infcx.tcx).skip_norm_wip(), + ty::ConstKind::Unevaluated(_, uv) => uv.type_of(infcx.tcx).skip_norm_wip(), ty::ConstKind::Param(param_ct) => { param_ct.find_const_ty_from_env(obligation.param_env) } diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index eeb41f3f3195b..6e0845f878958 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -213,7 +213,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { "cannot use `instantiate_impl_args` with a `NormalizesTo` goal" ); - return eager_resolve_vars(infcx, impl_args); + return eager_resolve_vars(&**infcx, impl_args); } inspect::ProbeStep::AddGoal(..) => {} inspect::ProbeStep::MakeCanonicalResponse { .. } @@ -441,7 +441,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> { infcx, depth, orig_values, - goal: eager_resolve_vars(infcx, uncanonicalized_goal), + goal: eager_resolve_vars(&**infcx, uncanonicalized_goal), result, final_revision, normalizes_to_term_hack: term_hack_and_nested_certainty.map(|(n, _)| n), diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 97b460fe347d8..69d86e485f2de 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::{ self, Binder, Flags, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, UniverseIndex, Unnormalized, }; -use rustc_next_trait_solver::normalize::NormalizationFolder; +use rustc_next_trait_solver::normalize::{NormalizationFolder, NormalizationWasAmbiguous}; use rustc_next_trait_solver::solve::SolverDelegateEvalExt; use super::{FulfillmentCtxt, NextSolverError}; @@ -42,28 +42,38 @@ where let infcx = at.infcx; let value = value.skip_normalization(); let value = infcx.resolve_vars_if_possible(value); + + if !infcx.tcx.renormalize_rigid_aliases() && !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, - infer_term, - 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)) - }); + 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_of_kind(alias_term, at.cause.span); + let predicate = ty::PredicateKind::AliasRelate( + alias_term, + infer_term, + 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(result.goal); + NormalizationWasAmbiguous::Yes + } + }; + Ok((normalized, normalization_was_ambiguous)) + }); if let Ok(value) = value.try_fold_with(&mut folder) { - let obligations = folder - .stalled_goals() + let obligations = stalled_goals .into_iter() .map(|goal| { Obligation::new(infcx.tcx, at.cause.clone(), goal.param_env, goal.predicate) diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 5331773e58bed..778890ace6362 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -552,7 +552,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { pub fn is_of_param(&self, ty: Ty<'tcx>) -> bool { match ty.kind() { ty::Param(_) => true, - ty::Alias(p @ ty::AliasTy { kind: ty::Projection { .. }, .. }) => { + ty::Alias(_, p @ ty::AliasTy { kind: ty::Projection { .. }, .. }) => { self.is_of_param(p.self_ty()) } _ => false, @@ -561,7 +561,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'tcx>) -> bool { if let Some(ty) = p.term().skip_binder().as_type() { - matches!(ty.kind(), ty::Alias(proj @ ty::AliasTy { kind: ty::Projection { .. }, .. }) if proj == &p.skip_binder().projection_term.expect_ty()) + matches!(ty.kind(), ty::Alias(_, proj @ ty::AliasTy { kind: ty::Projection { .. }, .. }) if proj == &p.skip_binder().projection_term.expect_ty()) } else { false } @@ -768,7 +768,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { } ty::PredicateKind::ConstEquate(c1, c2) => { let evaluate = |c: ty::Const<'tcx>| { - if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() { + if let ty::ConstKind::Unevaluated(_, unevaluated) = c.kind() { let ct = super::try_evaluate_const(selcx.infcx, c, obligation.param_env); diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index fd6505c94f61a..4581e4d8684f3 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -543,7 +543,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/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index cd9acde9d7b99..16009e5295f27 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -30,7 +30,7 @@ pub fn is_const_evaluatable<'tcx>( ) -> Result<(), NotConstEvaluatable> { let tcx = infcx.tcx; match tcx.expand_abstract_consts(unexpanded_ct).kind() { - ty::ConstKind::Unevaluated(_) | ty::ConstKind::Expr(_) => (), + ty::ConstKind::Unevaluated(_, _) | ty::ConstKind::Expr(_) => (), ty::ConstKind::Param(_) | ty::ConstKind::Bound(_, _) | ty::ConstKind::Placeholder(_) @@ -44,10 +44,10 @@ pub fn is_const_evaluatable<'tcx>( let is_anon_ct = matches!( ct.kind(), - ty::ConstKind::Unevaluated(ty::UnevaluatedConst { - kind: ty::UnevaluatedConstKind::Anon { .. }, - .. - }) + ty::ConstKind::Unevaluated( + _, + ty::UnevaluatedConst { kind: ty::UnevaluatedConstKind::Anon { .. }, .. } + ) ); if !is_anon_ct { @@ -69,7 +69,7 @@ pub fn is_const_evaluatable<'tcx>( // here. tcx.dcx().span_bug(span, "evaluating `ConstKind::Expr` is not currently supported"); } - ty::ConstKind::Unevaluated(_) => { + ty::ConstKind::Unevaluated(_, _) => { match crate::traits::try_evaluate_const(infcx, unexpanded_ct, param_env) { Err(EvaluateConstErr::HasGenericsOrInfers) => { Err(NotConstEvaluatable::Error(infcx.dcx().span_delayed_bug( @@ -94,7 +94,7 @@ pub fn is_const_evaluatable<'tcx>( Ok(()) } else { let uv = match unexpanded_ct.kind() { - ty::ConstKind::Unevaluated(uv) => uv, + ty::ConstKind::Unevaluated(_, uv) => uv, ty::ConstKind::Expr(_) => { bug!("`ConstKind::Expr` without `feature(generic_const_exprs)` enabled") } diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index f20c97e443984..36a562ab862fa 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -604,7 +604,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 @@ -859,13 +859,13 @@ impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> { ControlFlow::Continue(()) } } - ty::Alias(ty::AliasTy { kind: ty::Projection { def_id }, .. }) + ty::Alias(_, ty::AliasTy { kind: ty::Projection { def_id }, .. }) if self.tcx.is_impl_trait_in_trait(*def_id) => { // We'll deny these later in their own pass ControlFlow::Continue(()) } - ty::Alias(proj @ ty::AliasTy { kind: ty::Projection { .. }, .. }) => { + ty::Alias(_, proj @ ty::AliasTy { kind: ty::Projection { .. }, .. }) => { match self.allow_self_projections { AllowSelfProjections::Yes => { // Only walk contained types if the parent trait is not a supertrait. @@ -886,11 +886,14 @@ impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> { let ct = self.tcx.expand_abstract_consts(ct); match ct.kind() { - ty::ConstKind::Unevaluated(ty::UnevaluatedConst { - kind: ty::UnevaluatedConstKind::Projection { def_id }, - args, - .. - }) if self.tcx.features().min_generic_const_args() => { + ty::ConstKind::Unevaluated( + _, + ty::UnevaluatedConst { + kind: ty::UnevaluatedConstKind::Projection { def_id }, + args, + .. + }, + ) if self.tcx.features().min_generic_const_args() => { match self.allow_self_projections { AllowSelfProjections::Yes => { let trait_def_id = self.tcx.parent(def_id); @@ -966,7 +969,7 @@ impl<'tcx> TypeVisitor> for IllegalRpititVisitor<'tcx> { type Result = ControlFlow; fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result { - if let ty::Alias(proj @ ty::AliasTy { kind: ty::Projection { def_id }, .. }) = *ty.kind() + if let ty::Alias(_, proj @ ty::AliasTy { kind: ty::Projection { def_id }, .. }) = *ty.kind() && Some(proj) != self.allowed && self.tcx.is_impl_trait_in_trait(def_id) { diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index b657992e2c7a0..d7086fe80e877 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -179,6 +179,7 @@ fn evaluate_host_effect_from_conditionally_const_item_bounds<'tcx>( let mut consider_ty = obligation.predicate.self_ty(); while let ty::Alias( + _, alias_ty @ ty::AliasTy { kind: kind @ (ty::Projection { def_id } | ty::Opaque { def_id }), .. @@ -275,6 +276,7 @@ fn evaluate_host_effect_from_item_bounds<'tcx>( let mut consider_ty = obligation.predicate.self_ty(); while let ty::Alias( + _, alias_ty @ ty::AliasTy { kind: kind @ (ty::Projection { def_id } | ty::Opaque { def_id }), .. @@ -377,7 +379,7 @@ fn evaluate_host_effect_for_copy_clone_goal<'tcx>( | ty::Foreign(..) | ty::Ref(_, _, ty::Mutability::Mut) | ty::Adt(_, _) - | ty::Alias(_) + | ty::Alias(_, _) | ty::Param(_) | ty::Placeholder(..) => Err(EvaluationFailure::NoSolution), diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index a77254e8428cf..ea2f17d266b78 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -559,7 +559,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { return ProcessResult::Changed(PendingPredicateObligations::new()); } ty::ConstKind::Value(cv) => cv.ty, - ty::ConstKind::Unevaluated(uv) => uv.type_of(infcx.tcx).skip_norm_wip(), + ty::ConstKind::Unevaluated(_, uv) => uv.type_of(infcx.tcx).skip_norm_wip(), // FIXME(generic_const_exprs): we should construct an alias like // `>::Output` when this is an `Expr` representing // `lhs + rhs`. @@ -717,13 +717,15 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { debug!("equating consts:\nc1= {:?}\nc2= {:?}", c1, c2); match (c1.kind(), c2.kind()) { - (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) - if a.kind == b.kind - && matches!( - a.kind, - ty::UnevaluatedConstKind::Projection { .. } - | ty::UnevaluatedConstKind::Inherent { .. } - ) => + ( + ty::ConstKind::Unevaluated(_, a), + ty::ConstKind::Unevaluated(_, b), + ) if a.kind == b.kind + && matches!( + a.kind, + ty::UnevaluatedConstKind::Projection { .. } + | ty::UnevaluatedConstKind::Inherent { .. } + ) => { if let Ok(new_obligations) = infcx .at(&obligation.cause, obligation.param_env) @@ -741,8 +743,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { )); } } - (_, ty::ConstKind::Unevaluated(_)) - | (ty::ConstKind::Unevaluated(_), _) => (), + (_, ty::ConstKind::Unevaluated(_, _)) + | (ty::ConstKind::Unevaluated(_, _), _) => (), (_, _) => { if let Ok(new_obligations) = infcx .at(&obligation.cause, obligation.param_env) @@ -762,7 +764,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { let stalled_on = &mut pending_obligation.stalled_on; let mut evaluate = |c: Const<'tcx>| { - if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() { + if let ty::ConstKind::Unevaluated(_, unevaluated) = c.kind() { match super::try_evaluate_const( self.selcx.infcx, c, diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 5ddfaf361940c..c062198861ebe 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -280,6 +280,9 @@ 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: opaque types in param env might be in defining scope but we're + // using non body analysis for here. So the rigidness marker is wrong. + let predicates = ty::set_aliases_to_non_rigid(tcx, predicates).skip_norm_wip(); let errors = ocx.evaluate_obligations_error_on_ambiguity(); if !errors.is_empty() { @@ -366,7 +369,7 @@ pub fn normalize_param_env_or_error<'tcx>( // should actually be okay since without `feature(generic_const_exprs)` the only // const arguments that have a non-empty param env are array repeat counts. These // do not appear in the type system though. - if let ty::ConstKind::Unevaluated(uv) = c.kind() + if let ty::ConstKind::Unevaluated(_, uv) = c.kind() && matches!(uv.kind, ty::UnevaluatedConstKind::Anon { .. }) { let infcx = self.0.infer_ctxt().build(TypingMode::non_body_analysis()); @@ -605,7 +608,7 @@ pub fn try_evaluate_const<'tcx>( | ty::ConstKind::Bound(_, _) | ty::ConstKind::Placeholder(_) | ty::ConstKind::Expr(_) => Err(EvaluateConstErr::HasGenericsOrInfers), - ty::ConstKind::Unevaluated(uv) => { + ty::ConstKind::Unevaluated(_, uv) => { let opt_anon_const_kind = match uv.kind { ty::UnevaluatedConstKind::Anon { def_id } => { Some((def_id, tcx.anon_const_kind(def_id))) @@ -923,7 +926,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/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 6dc378718d639..9007b74e8fa16 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -229,7 +229,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { ) .ok() .flatten() - .unwrap_or_else(|| proj.to_term(infcx.tcx)); + .unwrap_or_else(|| proj.to_term(infcx.tcx, ty::IsRigid::No)); PlaceholderReplacer::replace_placeholders( infcx, @@ -395,7 +395,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx return ty; } - let ty::Alias(data) = *ty.kind() else { return ty.super_fold_with(self) }; + let ty::Alias(_, data) = *ty.kind() else { return ty.super_fold_with(self) }; // We try to be a little clever here as a performance optimization in // cases where there are nested projections under binders. @@ -463,14 +463,14 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx if tcx.features().generic_const_exprs() // Normalize type_const items even with feature `generic_const_exprs`. - && !matches!(ct.kind(), ty::ConstKind::Unevaluated(uv) if uv.kind.is_type_const(tcx)) + && !matches!(ct.kind(), ty::ConstKind::Unevaluated(_, uv) if uv.kind.is_type_const(tcx)) || !needs_normalization(self.selcx.infcx, &ct) { return ct; } let uv = match ct.kind() { - ty::ConstKind::Unevaluated(uv) => uv, + ty::ConstKind::Unevaluated(_, uv) => uv, _ => return ct.super_fold_with(self), }; diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index e267d18515a40..e2257703f5775 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -738,7 +738,7 @@ fn project<'cx, 'tcx>( } ProjectionCandidateSet::None => { let tcx = selcx.tcx(); - let term = obligation.predicate.to_term(tcx); + let term = obligation.predicate.to_term(tcx, ty::IsRigid::No); Ok(Projected::NoProgress(term)) } // Error occurred while trying to processing impls. @@ -1583,7 +1583,7 @@ fn confirm_builtin_candidate<'cx, 'tcx>( } else { // We know that `self_ty` has the same metadata as `tail`. This allows us // to prove predicates like `Wrapper::Metadata == Tail::Metadata`. - Ty::new_projection(tcx, metadata_def_id, [tail]) + Ty::new_projection(tcx, ty::IsRigid::No, metadata_def_id, [tail]) } }); (metadata_ty.into(), obligations) @@ -1678,6 +1678,7 @@ fn confirm_closure_candidate<'cx, 'tcx>( tcx.require_lang_item(LangItem::AsyncFnKindUpvars, obligation.cause.span); let tupled_upvars_ty = Ty::new_projection( tcx, + ty::IsRigid::No, upvars_projection_def_id, [ ty::GenericArg::from(kind_ty), @@ -1807,6 +1808,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( // N.B. No need to register a `AsyncFnKindHelper` goal here, it's already in `nested`. let tupled_upvars_ty = Ty::new_projection( tcx, + ty::IsRigid::No, upvars_projection_def_id, [ ty::GenericArg::from(kind_ty), @@ -1855,7 +1857,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( sym::Output => { let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, obligation.cause.span); - Ty::new_projection(tcx, future_output_def_id, [sig.output()]) + Ty::new_projection(tcx, ty::IsRigid::No, future_output_def_id, [sig.output()]) } name => bug!("no such associated type: {name}"), }; @@ -1889,7 +1891,7 @@ fn confirm_async_closure_candidate<'cx, 'tcx>( sym::Output => { let future_output_def_id = tcx.require_lang_item(LangItem::FutureOutput, obligation.cause.span); - Ty::new_projection(tcx, future_output_def_id, [sig.output()]) + Ty::new_projection(tcx, ty::IsRigid::No, future_output_def_id, [sig.output()]) } name => bug!("no such associated type: {name}"), }; @@ -2058,7 +2060,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( // `Projected::NoProgress`. This will ensure that the projection is // checked for well-formedness, and it's either satisfied by a trivial // where clause in its env or it results in an error. - return Ok(Projected::NoProgress(obligation.predicate.to_term(tcx))); + return Ok(Projected::NoProgress(obligation.predicate.to_term(tcx, ty::IsRigid::No))); } else { return Ok(Projected::Progress(Progress { term: if obligation.predicate.kind.is_type() { 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 d8d31fb7be196..45a3b5c85cdc8 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -203,7 +203,7 @@ impl<'a, 'tcx> FallibleTypeFolder> for QueryNormalizer<'a, 'tcx> { return Ok(*ty); } - let &ty::Alias(data) = ty.kind() else { + let &ty::Alias(_, data) = ty.kind() else { let res = ty.try_super_fold_with(self)?; self.cache.insert(ty, res); return Ok(res); @@ -273,7 +273,7 @@ impl<'a, 'tcx> FallibleTypeFolder> for QueryNormalizer<'a, 'tcx> { } let uv = match constant.kind() { - ty::ConstKind::Unevaluated(uv) => uv, + ty::ConstKind::Unevaluated(_, uv) => uv, _ => return constant.try_super_fold_with(self), }; @@ -377,7 +377,7 @@ impl<'a, 'tcx> QueryNormalizer<'a, 'tcx> { // Similarly, `tcx.normalize_canonicalized_free_alias` will only unwrap one layer // of type/const and we need to continue folding it to reveal the TAIT behind it // or further normalize nested unevaluated consts. - if res != term.to_term(tcx) + if res != term.to_term(tcx, ty::IsRigid::No) && (res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) || matches!( term.kind, diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 3b599db8ff1c2..b278c32cb61ae 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -194,7 +194,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // quickly check if the self-type is a projection at all. match obligation.predicate.skip_binder().trait_ref.self_ty().kind() { // Excluding IATs and type aliases here as they don't have meaningful item bounds. - ty::Alias(ty::AliasTy { kind: ty::Projection { .. } | ty::Opaque { .. }, .. }) => {} + ty::Alias(_, ty::AliasTy { kind: ty::Projection { .. } | ty::Opaque { .. }, .. }) => {} ty::Infer(ty::TyVar(_)) => { span_bug!( obligation.cause.span, @@ -681,7 +681,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // These may potentially implement `FnPtr` ty::Placeholder(..) | ty::Dynamic(_, _) - | ty::Alias(_) + | ty::Alias(_, _) | ty::Infer(_) | ty::Param(..) | ty::Bound(_, _) => {} @@ -784,10 +784,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } ty::Param(..) - | ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }, - .. - }) + | ty::Alias( + _, + ty::AliasTy { + kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }, + .. + }, + ) | ty::Placeholder(..) | ty::Bound(..) => { // In these cases, we don't know what the actual @@ -838,7 +841,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); } - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }) => { if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate { .. })) { // We do not generate an auto impl candidate for `impl Trait`s which already // reference our auto trait. diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 6e55b901bfadf..e33311ed07719 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -882,13 +882,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); match (c1.kind(), c2.kind()) { - (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b)) - if a.kind == b.kind - && matches!( - a.kind, - ty::UnevaluatedConstKind::Projection { .. } - | ty::UnevaluatedConstKind::Inherent { .. } - ) => + ( + ty::ConstKind::Unevaluated(_, a), + ty::ConstKind::Unevaluated(_, b), + ) if a.kind == b.kind + && matches!( + a.kind, + ty::UnevaluatedConstKind::Projection { .. } + | ty::UnevaluatedConstKind::Inherent { .. } + ) => { if let Ok(InferOk { obligations, value: () }) = self .infcx @@ -907,8 +909,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); } } - (_, ty::ConstKind::Unevaluated(_)) - | (ty::ConstKind::Unevaluated(_), _) => (), + (_, ty::ConstKind::Unevaluated(_, _)) + | (ty::ConstKind::Unevaluated(_, _), _) => (), (_, _) => { if let Ok(InferOk { obligations, value: () }) = self .infcx @@ -927,7 +929,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } let evaluate = |c: ty::Const<'tcx>| { - if let ty::ConstKind::Unevaluated(_) = c.kind() { + if let ty::ConstKind::Unevaluated(_, _) = c.kind() { match crate::traits::try_evaluate_const( self.infcx, c, @@ -987,7 +989,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::ConstKind::Error(_) => return Ok(EvaluatedToOk), ty::ConstKind::Value(cv) => cv.ty, - ty::ConstKind::Unevaluated(uv) => uv.type_of(self.tcx()).skip_norm_wip(), + ty::ConstKind::Unevaluated(_, uv) => uv.type_of(self.tcx()).skip_norm_wip(), // FIXME(generic_const_exprs): See comment in `fulfill.rs` ty::ConstKind::Expr(_) => return Ok(EvaluatedToOk), ty::ConstKind::Placeholder(_) => { @@ -1658,6 +1660,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { loop { let (alias_ty, def_id) = match *self_ty.kind() { ty::Alias( + _, alias_ty @ ty::AliasTy { kind: ty::Projection { def_id } | ty::Opaque { def_id }, .. @@ -2348,10 +2351,13 @@ impl<'tcx> SelectionContext<'_, 'tcx> { ty::Placeholder(..) | ty::Dynamic(..) | ty::Param(..) - | ty::Alias(ty::AliasTy { - kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }, - .. - }) + | ty::Alias( + _, + ty::AliasTy { + kind: ty::Projection { .. } | ty::Inherent { .. } | ty::Free { .. }, + .. + }, + ) | ty::Bound(..) | ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { bug!("asked to assemble constituent types of unexpected type: {:?}", t); @@ -2420,7 +2426,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { assumptions: vec![], }), - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => { + ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => { if self.infcx.can_define_opaque_ty(def_id) { unreachable!() } else { diff --git a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs index 03edfeb06d8c4..648e936e4189a 100644 --- a/compiler/rustc_trait_selection/src/traits/structural_normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/structural_normalize.rs @@ -41,10 +41,15 @@ impl<'tcx> At<'_, 'tcx> { if self.infcx.next_trait_solver() { let term = term.skip_normalization(); - if let None = term.to_alias_term() { + + if !self.infcx.tcx.renormalize_rigid_aliases() && !term.is_non_rigid_alias() { return Ok(term); } + let Some(_) = term.to_alias_term() else { + return Ok(term); + }; + let new_infer = self.infcx.next_term_var_of_kind(term, self.cause.span); // We simply emit an `alias-eq` goal here, since that will take care of diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 8eec1d85a0ea0..8b1b2acc1f5a3 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -284,7 +284,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>( }; let ty_to_impl_span = |ty: Ty<'_>| { - if let ty::Alias(ty::AliasTy { kind: ty::Projection { def_id }, .. }) = ty.kind() + if let ty::Alias(_, ty::AliasTy { kind: ty::Projection { def_id }, .. }) = ty.kind() && let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(def_id) && let Some(impl_item) = items.iter().find(|item| item.owner_id.to_def_id() == impl_item_id) @@ -801,15 +801,18 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { // Simple cases that are WF if their type args are WF. } - ty::Alias(ty::AliasTy { - kind: ty::Projection { def_id } | ty::Opaque { def_id } | ty::Free { def_id }, - args, - .. - }) => { + ty::Alias( + _, + ty::AliasTy { + kind: ty::Projection { def_id } | ty::Opaque { def_id } | ty::Free { def_id }, + args, + .. + }, + ) => { let obligations = self.nominal_obligations(def_id, args); self.out.extend(obligations); } - ty::Alias(data @ ty::AliasTy { kind: ty::Inherent { .. }, .. }) => { + ty::Alias(_, data @ ty::AliasTy { kind: ty::Inherent { .. }, .. }) => { self.add_wf_preds_for_inherent_projection(data.into()); return; // Subtree handled by compute_inherent_projection. } @@ -1061,7 +1064,7 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { let tcx = self.tcx(); match c.kind() { - ty::ConstKind::Unevaluated(uv) => { + ty::ConstKind::Unevaluated(_, uv) => { if !c.has_escaping_bound_vars() { // Skip type consts as mGCA doesn't support evaluatable clauses if !uv.kind.is_type_const(tcx) && !tcx.features().generic_const_args() { diff --git a/compiler/rustc_traits/src/coroutine_witnesses.rs b/compiler/rustc_traits/src/coroutine_witnesses.rs index 5bfbda9d90e6b..c2f517d6019c6 100644 --- a/compiler/rustc_traits/src/coroutine_witnesses.rs +++ b/compiler/rustc_traits/src/coroutine_witnesses.rs @@ -38,10 +38,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 85bc9b985a277..52964ae72f015 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -75,7 +75,7 @@ fn recurse_build<'tcx>( ty::UnevaluatedConstKind::new_from_def_id(tcx, def_id), args, ); - ty::Const::new_unevaluated(tcx, uneval) + ty::Const::new_unevaluated(tcx, ty::IsRigid::No, uneval) } ExprKind::ConstParam { param, .. } => ty::Const::new_param(tcx, *param), @@ -385,7 +385,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..e83525c16b965 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -116,7 +116,7 @@ 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)) + ty::EarlyBinder::bind_iter(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 eb0cc98736adb..df46ba9ce57e5 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -46,13 +46,16 @@ fn layout_of<'tcx>( // the where bounds to their hidden types. This reduces overall uncached invocations // of `layout_of` and is thus a small performance improvement. let typing_env = typing_env.with_post_analysis_normalized(tcx); + // Changing typing env may reveal opaque types that's marked as rigid in other + // typing env. + let non_rigid_ty = ty::set_aliases_to_non_rigid(tcx, ty); let unnormalized_ty = ty; // FIXME: We might want to have two different versions of `layout_of`: // 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 normalized_ty = match tcx.try_normalize_erasing_regions(typing_env, non_rigid_ty) { Ok(t) => t, Err(normalization_error) => { return Err(tcx @@ -61,9 +64,11 @@ fn layout_of<'tcx>( } }; - if ty != unnormalized_ty { + if normalized_ty != unnormalized_ty { + // FIXME: our rigidness folding is redundant in this case. + // // Ensure this layout is also cached for the normalized type. - return tcx.layout_of(typing_env.as_query_input(ty)); + return tcx.layout_of(typing_env.as_query_input(normalized_ty)); } match typing_env.typing_mode() { @@ -86,8 +91,8 @@ fn layout_of<'tcx>( let cx = LayoutCx::new(tcx, typing_env); - let layout = layout_of_uncached(&cx, ty)?; - let layout = TyAndLayout { ty, layout }; + let layout = layout_of_uncached(&cx, normalized_ty)?; + let layout = TyAndLayout { ty: normalized_ty, layout }; // If we are running with `-Zprint-type-sizes`, maybe record layouts // for dumping later. @@ -170,7 +175,7 @@ fn extract_const_value<'tcx>( } Err(error(cx, LayoutError::TooGeneric(ty))) } - ty::ConstKind::Unevaluated(_) => { + ty::ConstKind::Unevaluated(_, _) => { let err = if ct.has_param() { LayoutError::TooGeneric(ty) } else { @@ -437,7 +442,8 @@ fn layout_of_uncached<'tcx>( } let metadata = if let Some(metadata_def_id) = tcx.lang_items().metadata_type() { - let pointee_metadata = Ty::new_projection(tcx, metadata_def_id, [pointee]); + let pointee_metadata = + Ty::new_projection(tcx, ty::IsRigid::No, metadata_def_id, [pointee]); let metadata_ty = match tcx.try_normalize_erasing_regions( cx.typing_env, Unnormalized::new_wip(pointee_metadata), @@ -557,7 +563,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 e2529e7a77226..136fe09929eef 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -222,7 +222,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(), ); @@ -374,7 +374,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/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index d95624b9a24d2..a8fa2ed87bb87 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -210,14 +210,14 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { fn visit_ty(&mut self, t: Ty<'tcx>) { t.super_visit_with(self); match *t.kind() { - ty::Alias(alias_ty @ ty::AliasTy { kind: ty::Opaque { def_id }, .. }) + ty::Alias(_, alias_ty @ ty::AliasTy { kind: ty::Opaque { def_id }, .. }) if def_id.is_local() => { self.visit_opaque_ty(alias_ty); } // Skips type aliases, as they are meant to be transparent. // FIXME(type_alias_impl_trait): can we require mentioning nested type aliases explicitly? - ty::Alias(ty::AliasTy { kind: ty::Free { def_id }, args, .. }) + ty::Alias(_, ty::AliasTy { kind: ty::Free { def_id }, args, .. }) if let Some(def_id) = def_id.as_local() => { if !self.seen.insert(def_id) { @@ -230,6 +230,7 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { .visit_with(self); } ty::Alias( + _, alias_ty @ ty::AliasTy { kind: ty::Projection { def_id: alias_def_id }, .. }, ) => { // This avoids having to do normalization of `Self::AssocTy` by only @@ -299,7 +300,7 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { .type_of(alias_def_id) .instantiate(self.tcx, alias_ty.args) .skip_norm_wip(); - let ty::Alias(alias_ty @ ty::AliasTy { kind: ty::Opaque { .. }, .. }) = + let ty::Alias(_, alias_ty @ ty::AliasTy { kind: ty::Opaque { .. }, .. }) = *ty.kind() else { bug!("{ty:?}") diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 367e2e1b97059..a28cafab30103 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. @@ -224,6 +224,7 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitFinder<'_, 'tcx> { fn visit_ty(&mut self, ty: Ty<'tcx>) { if let ty::Alias( + _, unshifted_alias_ty @ ty::AliasTy { kind: ty::Projection { def_id: unshifted_alias_ty_def_id }, .. @@ -391,7 +392,7 @@ fn impl_self_is_guaranteed_unsized<'tcx>(tcx: TyCtxt<'tcx>, impl_def_id: DefId) | ty::CoroutineWitness(_, _) | ty::Never | ty::Tuple(_) - | ty::Alias(_) + | ty::Alias(_, _) | ty::Param(_) | ty::Bound(_, _) | ty::Placeholder(_) diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index dbd8beed2ed26..66daaf958879b 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -369,11 +369,32 @@ generate!( impl !TypeVisitable for ty::EarlyBinder {} ); -impl EarlyBinder { - pub fn bind(value: T) -> EarlyBinder { +impl> EarlyBinder { + pub fn bind(cx: I, value: T) -> EarlyBinder { + let value = ty::set_aliases_to_non_rigid(cx, value).skip_normalization(); EarlyBinder { value, _tcx: PhantomData } } +} + +impl> + Clone> EarlyBinder { + pub fn bind_iter(value: T) -> EarlyBinder { + #[cfg(debug_assertions)] + { + value.clone().into_iter().for_each(|v| assert!(!v.has_rigid_aliases())); + } + EarlyBinder { value, _tcx: PhantomData } + } +} + +impl> EarlyBinder { + pub fn bind_no_rigid_aliases(value: T) -> EarlyBinder { + debug_assert!(!value.has_rigid_aliases()); + EarlyBinder { value, _tcx: PhantomData } + } +} + +impl EarlyBinder { pub fn as_ref(&self) -> EarlyBinder { EarlyBinder { value: &self.value, _tcx: PhantomData } } @@ -523,6 +544,14 @@ pub struct IterInstantiatedCopied<'a, I: Interner, Iter: IntoIterator> { args: &'a [I::GenericArg], } +impl<'a, I: Interner, Iter: IntoIterator> Clone + for IterInstantiatedCopied<'a, I, Iter> +{ + fn clone(&self) -> IterInstantiatedCopied<'a, I, Iter> { + IterInstantiatedCopied { it: self.it.clone(), cx: self.cx, args: self.args } + } +} + impl Iterator for IterInstantiatedCopied<'_, I, Iter> where Iter::Item: Deref, @@ -567,6 +596,12 @@ pub struct IterIdentityCopied { _tcx: PhantomData I>, } +impl> Clone for IterIdentityCopied { + fn clone(&self) -> IterIdentityCopied { + IterIdentityCopied { it: self.it.clone(), _tcx: self._tcx } + } +} + impl Iterator for IterIdentityCopied where Iter::Item: Deref, diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index b3a33b775ad10..365825e1c28cc 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -34,7 +34,7 @@ pub enum ConstKind { /// An unnormalized const item such as an anon const or assoc const or free const item. /// Right now anything other than anon consts does not actually work properly but this /// should - Unevaluated(ty::UnevaluatedConst), + Unevaluated(ty::IsRigid, ty::UnevaluatedConst), /// Used to hold computed value. Value(I::ValueConst), @@ -59,7 +59,7 @@ impl fmt::Debug for ConstKind { Infer(var) => write!(f, "{var:?}"), Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var), Placeholder(placeholder) => write!(f, "{placeholder:?}"), - Unevaluated(uv) => write!(f, "{uv:?}"), + Unevaluated(is_rigid, uv) => write!(f, "Unevaluated({is_rigid:?}, {uv:?})"), Value(val) => write!(f, "{val:?}"), Error(_) => write!(f, "{{const error}}"), Expr(expr) => write!(f, "{expr:?}"), diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs index be3661518d7d9..aae921249b4f4 100644 --- a/compiler/rustc_type_ir/src/elaborate.rs +++ b/compiler/rustc_type_ir/src/elaborate.rs @@ -276,7 +276,7 @@ fn elaborate_component_to_clause( // We might end up here if we have `Foo<::Assoc>: 'a`. // With this, we can deduce that `::Assoc: 'a`. Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( - alias_ty.to_ty(cx), + alias_ty.to_ty(cx, ty::IsRigid::No), outlives_region, ))) } @@ -414,7 +414,10 @@ pub fn elaborate_outlives_assumptions( } Component::Alias(alias_ty) => { - collected.insert(ty::OutlivesPredicate(alias_ty.to_ty(cx).into(), r2)); + collected.insert(ty::OutlivesPredicate( + alias_ty.to_ty(cx, ty::IsRigid::No).into(), + r2, + )); } Component::UnresolvedInferenceVariable(_) | Component::EscapingAlias(_) => { diff --git a/compiler/rustc_type_ir/src/error.rs b/compiler/rustc_type_ir/src/error.rs index aa4785439813f..c08cec21e5b1f 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..77d15d45f1b33 100644 --- a/compiler/rustc_type_ir/src/fast_reject.rs +++ b/compiler/rustc_type_ir/src/fast_reject.rs @@ -261,6 +261,7 @@ impl return true, ty::Infer(var) => return self.var_and_ty_may_unify(var, lhs), @@ -468,7 +469,7 @@ impl { @@ -499,7 +500,7 @@ impl { + ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_, _) | ty::ConstKind::Error(_) => { true } diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 19c59df0604c3..1749ec99cad4e 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -146,6 +146,18 @@ bitflags::bitflags! { /// Does this have a `Bound(BoundVarIndexKind::Canonical, _)`? const HAS_CANONICAL_BOUND = 1 << 26; + + /// Does this have any aliases with `IsRigid::Yes`? + /// + /// We have both rigid and non-rigid flags because both can be true for a single + /// subject. E.g. one arg is rigid while another is non-rigid for some ADTs. + const HAS_RIGID_ALIAS = 1 << 27; + + /// Does this have any aliases with `IsRigid::No`? + /// + /// We have a separate flag from `HAS_ALIAS` because `HAS_ALIAS` doesn't care + /// about rigidness while we rely on rigidness to skip renormalization. + const HAS_NON_RIGID_ALIAS = 1 << 28; } } @@ -295,14 +307,14 @@ impl FlagComputation { self.add_args(args.as_slice()); } - ty::Alias(alias) => { + ty::Alias(is_rigid, alias) => { + self.add_is_rigid(is_rigid); self.add_flags(match alias.kind { ty::Projection { .. } => TypeFlags::HAS_TY_PROJECTION, ty::Free { .. } => TypeFlags::HAS_TY_FREE_ALIAS, ty::Opaque { .. } => TypeFlags::HAS_TY_OPAQUE, ty::Inherent { .. } => TypeFlags::HAS_TY_INHERENT, }); - self.add_alias_ty(alias); } @@ -465,7 +477,8 @@ impl FlagComputation { fn add_const_kind(&mut self, c: &ty::ConstKind) { match *c { - ty::ConstKind::Unevaluated(uv) => { + ty::ConstKind::Unevaluated(is_rigid, uv) => { + self.add_is_rigid(is_rigid); self.add_args(uv.args.as_slice()); self.add_flags(TypeFlags::HAS_CT_PROJECTION); } @@ -529,6 +542,13 @@ impl FlagComputation { } } + fn add_is_rigid(&mut self, is_rigid: ty::IsRigid) { + match is_rigid { + ty::IsRigid::Yes => self.add_flags(TypeFlags::HAS_RIGID_ALIAS), + ty::IsRigid::No => self.add_flags(TypeFlags::HAS_NON_RIGID_ALIAS), + } + } + fn add_term(&mut self, term: I::Term) { match term.kind() { ty::TermKind::Ty(ty) => self.add_ty(ty), diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index 0fe68b5256691..99a1028209e2d 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -554,3 +554,66 @@ where if c.has_regions() { c.super_fold_with(self) } else { c } } } + +pub fn set_aliases_to_non_rigid(cx: I, value: T) -> ty::Unnormalized +where + T: TypeFoldable, +{ + if !value.has_rigid_aliases() { + return ty::Unnormalized::new(value); + } + + let mut folder = RigidnessFolder { cx }; + ty::Unnormalized::new(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(ty::IsRigid::Yes, alias_ty) => { + let alias_ty = alias_ty.fold_with(self); + I::Ty::new_alias(self.cx(), ty::IsRigid::No, alias_ty) + } + _ => t.super_fold_with(self), + } + } + + fn fold_const(&mut self, c: I::Const) -> I::Const { + if !c.has_rigid_aliases() { + return c; + } + + match c.kind() { + ty::ConstKind::Unevaluated(ty::IsRigid::Yes, uv) => { + let uv = uv.fold_with(self); + I::Const::new_unevaluated(self.cx, ty::IsRigid::No, uv) + } + _ => c.super_fold_with(self), + } + } + + 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 e0fe608198921..44cc25d7b6f99 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -53,26 +53,30 @@ pub trait Ty>: fn new_canonical_bound(interner: I, var: ty::BoundVar) -> Self; - fn new_alias(interner: I, alias_ty: ty::AliasTy) -> Self; + fn new_alias(interner: I, is_rigid: ty::IsRigid, alias_ty: ty::AliasTy) -> Self; fn new_projection_from_args( interner: I, + is_rigid: ty::IsRigid, def_id: I::TraitAssocTyId, args: I::GenericArgs, ) -> Self { Self::new_alias( interner, + is_rigid, ty::AliasTy::new_from_args(interner, ty::AliasTyKind::Projection { def_id }, args), ) } fn new_projection( interner: I, + is_rigid: ty::IsRigid, def_id: I::TraitAssocTyId, args: impl IntoIterator>, ) -> Self { Self::new_alias( interner, + is_rigid, ty::AliasTy::new(interner, ty::AliasTyKind::Projection { def_id }, args), ) } @@ -190,7 +194,7 @@ pub trait Ty>: | ty::CoroutineWitness(_, _) | ty::Never | ty::Tuple(_) - | ty::Alias(_) + | ty::Alias(_, _) | ty::Param(_) | ty::Bound(_, _) | ty::Placeholder(_) @@ -276,7 +280,7 @@ pub trait Const>: fn new_placeholder(interner: I, param: ty::PlaceholderConst) -> Self; - fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst) -> Self; + fn new_unevaluated(interner: I, is_rigid: ty::IsRigid, uv: ty::UnevaluatedConst) -> Self; fn new_expr(interner: I, expr: I::ExprConst) -> Self; @@ -403,15 +407,28 @@ pub trait Term>: fn to_alias_term(self) -> Option> { match self.kind() { ty::TermKind::Ty(ty) => match ty.kind() { - ty::Alias(alias_ty) => Some(alias_ty.into()), + ty::Alias(_, alias_ty) => Some(alias_ty.into()), _ => None, }, ty::TermKind::Const(ct) => match ct.kind() { - ty::ConstKind::Unevaluated(uv) => Some(uv.into()), + ty::ConstKind::Unevaluated(_, uv) => Some(uv.into()), _ => None, }, } } + + fn is_non_rigid_alias(self) -> bool { + match self.kind() { + ty::TermKind::Ty(ty) => match ty.kind() { + ty::Alias(is_rigid, _) => is_rigid == ty::IsRigid::No, + _ => false, + }, + ty::TermKind::Const(ct) => match ct.kind() { + ty::ConstKind::Unevaluated(is_rigid, _) => is_rigid == ty::IsRigid::No, + _ => false, + }, + } + } } #[rust_analyzer::prefer_underscore_import] diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 5a98ff74cea42..1c1fbcff0d928 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -292,6 +292,8 @@ pub trait Interner: fn assumptions_on_binders(self) -> bool; + fn renormalize_rigid_aliases(self) -> bool; + fn coroutine_hidden_types( self, def_id: Self::CoroutineId, diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs index 2a1cbc3575d85..9bd687b891177 100644 --- a/compiler/rustc_type_ir/src/outlives.rs +++ b/compiler/rustc_type_ir/src/outlives.rs @@ -148,7 +148,7 @@ impl TypeVisitor for OutlivesCollector<'_, I> { // trait-ref. Therefore, if we see any higher-ranked regions, // we simply fallback to the most restrictive rule, which // requires that `Pi: 'a` for all `i`. - ty::Alias(alias_ty) => { + ty::Alias(_is_rigid, alias_ty) => { if !alias_ty.has_escaping_bound_vars() { // best case: no escaping regions, so push the // projection and skip the subtree (thus generating no diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index a7f7c2fa44358..b24b5b61b47e0 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -745,13 +745,15 @@ impl AliasTerm { ty::UnevaluatedConst { kind, args: self.args, _use_unevaluated_const_new_instead: () } } - pub fn to_term(self, interner: I) -> I::Term { + pub fn to_term(self, interner: I, is_rigid: ty::IsRigid) -> I::Term { let alias_ty = |kind| { - Ty::new_alias(interner, ty::AliasTy::new_from_args(interner, kind, self.args)).into() + Ty::new_alias(interner, is_rigid, ty::AliasTy::new_from_args(interner, kind, self.args)) + .into() }; let unevaluated_const = |kind| { I::Const::new_unevaluated( interner, + is_rigid, ty::UnevaluatedConst::new(interner, kind, self.args), ) .into() diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index 4b23bfd0f7765..a03e8254c8423 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -52,9 +52,9 @@ use crate::relate::{Relate, RelateResult, TypeRelation, VarianceDiagInfo}; use crate::visit::TypeSuperVisitable; use crate::{ AliasTy, Binder, BoundRegion, BoundVar, BoundVariableKind, ConstKind, DebruijnIndex, - FallibleTypeFolder, InferCtxtLike, InferTy, Interner, OutlivesPredicate, RegionKind, TyKind, - TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor, TypingMode, UniverseIndex, Variance, - VisitorResult, + FallibleTypeFolder, InferCtxtLike, InferTy, Interner, IsRigid, OutlivesPredicate, RegionKind, + TyKind, TypeFoldable, TypeFolder, TypeVisitable, TypeVisitor, TypingMode, UniverseIndex, + Variance, VisitorResult, }; #[derive_where(Clone, Debug; I: Interner)] @@ -1106,7 +1106,7 @@ fn alias_outlives_candidates_from_assumptions region_constraints: vec![RegionConstraint::RegionOutlives(r2, r)], }; - if let Ok(_) = relation.relate(alias.to_ty(infcx.cx()), alias2) { + if let Ok(_) = relation.relate(alias.to_ty(infcx.cx(), IsRigid::No), alias2) { candidates .push(RegionConstraint::And(relation.region_constraints.into_boxed_slice())); } diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 1ce09d7d5b5e8..500d502cd1ba5 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -222,7 +222,7 @@ impl Relate for ty::AliasTy { } else { relate_args_invariantly(relation, a.args, b.args)? }; - Ok(ty::AliasTy::new_from_args(cx, a.kind, args)) + Ok(ty::AliasTy::new_from_args(relation.cx(), a.kind, args)) } } } @@ -236,8 +236,8 @@ impl Relate for ty::UnevaluatedConst { let cx = relation.cx(); if a.kind != b.kind { Err(TypeError::ConstMismatch(ExpectedFound::new( - Const::new_unevaluated(cx, a), - Const::new_unevaluated(cx, b), + Const::new_unevaluated(cx, ty::IsRigid::Yes, a), + Const::new_unevaluated(cx, ty::IsRigid::Yes, b), ))) } else { // FIXME(mgca): remove this @@ -523,9 +523,12 @@ pub fn structurally_relate_tys>( } // Alias tend to mostly already be handled downstream due to normalization. - (ty::Alias(a), ty::Alias(b)) => { - let alias_ty = relation.relate(a, b)?; - Ok(Ty::new_alias(cx, alias_ty)) + (ty::Alias(is_rigid_a, alias_a), ty::Alias(is_rigid_b, alias_b)) => { + // Users shouldn't know about this so the mismatch should be caught + // during development rather than presented as type error. + debug_assert_eq!(is_rigid_a, is_rigid_b, "{a:?} != {b:?}"); + let alias_ty = relation.relate(alias_a, alias_b)?; + Ok(Ty::new_alias(cx, is_rigid_a, alias_ty)) } (ty::Pat(a_ty, a_pat), ty::Pat(b_ty, b_pat)) => { @@ -611,8 +614,14 @@ 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)) => { - return Ok(Const::new_unevaluated(cx, relation.relate(au, bu)?)); + ( + ty::ConstKind::Unevaluated(is_rigid_a, au), + ty::ConstKind::Unevaluated(is_rigid_b, bu), + ) => { + // Users shouldn't know about this so the mismatch should be caught + // during development rather than presented as type error. + debug_assert_eq!(is_rigid_a, is_rigid_b, "{a:?} != {b:?}"); + return Ok(Const::new_unevaluated(cx, is_rigid_a, relation.relate(au, bu)?)); } (ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => { let expr = relation.relate(ae, be)?; diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index 782e1fd7e37b4..7eaeb48c7ca9c 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -115,6 +115,19 @@ where panic!("We do not expect to encounter `Fresh` variables in the new solver") } + (ty::Alias(is_rigid_a, _), ty::Alias(is_rigid_b, _)) if infcx.next_trait_solver() => { + match (is_rigid_a, is_rigid_b) { + (ty::IsRigid::Yes, ty::IsRigid::Yes) => structurally_relate_tys(relation, a, b), + _ => match relation.structurally_relate_aliases() { + StructurallyRelateAliases::Yes => structurally_relate_tys(relation, a, b), + StructurallyRelateAliases::No => { + relation.register_alias_relate_predicate(a, b); + Ok(a) + } + }, + } + } + (_, ty::Alias(..)) | (ty::Alias(..), _) if infcx.next_trait_solver() => { match relation.structurally_relate_aliases() { StructurallyRelateAliases::Yes => structurally_relate_tys(relation, a, b), @@ -128,8 +141,8 @@ where // All other cases of inference are errors (ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Sorts(ExpectedFound::new(a, b))), - (ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }), _) - | (_, ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. })) => { + (ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }), _) + | (_, ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. })) => { assert!(!infcx.next_trait_solver()); match infcx.typing_mode_raw().assert_not_erased() { // During coherence, opaque types should be treated as *possibly* @@ -201,6 +214,13 @@ where Ok(a) } + ( + ty::ConstKind::Unevaluated(ty::IsRigid::Yes, _), + ty::ConstKind::Unevaluated(ty::IsRigid::Yes, _), + ) if (infcx.cx().features().generic_const_exprs() || infcx.next_trait_solver()) => { + structurally_relate_consts(relation, a, b) + } + (ty::ConstKind::Unevaluated(..), _) | (_, ty::ConstKind::Unevaluated(..)) if infcx.cx().features().generic_const_exprs() || infcx.next_trait_solver() => { diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 784a91424156f..847b22a4040d6 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -84,6 +84,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 @@ -250,7 +261,7 @@ pub enum TyKind { /// /// All of these types are represented as pairs of def-id and args, and can /// be normalized, so they are grouped conceptually. - Alias(AliasTy), + Alias(IsRigid, AliasTy), /// A type parameter; for example, `T` in `fn f(x: T) {}`. Param(I::ParamTy), @@ -352,7 +363,7 @@ impl TyKind { ty::Error(_) | ty::Infer(_) - | ty::Alias(_) + | ty::Alias(ty::IsRigid::No | ty::IsRigid::Yes, _) | ty::Param(_) | ty::Bound(_, _) | ty::Placeholder(_) => false, @@ -417,7 +428,7 @@ impl fmt::Debug for TyKind { } write!(f, ")") } - Alias(a) => f.debug_tuple("Alias").field(&a).finish(), + Alias(is_rigid, a) => f.debug_tuple("Alias").field(&is_rigid).field(&a).finish(), Param(p) => write!(f, "{p:?}"), Bound(d, b) => crate::debug_bound_var(f, *d, b), Placeholder(p) => write!(f, "{p:?}"), @@ -482,8 +493,8 @@ impl AliasTy { matches!(self.kind, AliasTyKind::Opaque { .. }) } - pub fn to_ty(self, interner: I) -> I::Ty { - Ty::new_alias(interner, self) + pub fn to_ty(self, interner: I, is_rigid: ty::IsRigid) -> I::Ty { + Ty::new_alias(interner, is_rigid, self) } } diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 492c37481298b..b77782b09ef85 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -167,6 +167,12 @@ impl, E: TypeVisitable> TypeVisitable for } } +impl> TypeVisitable for &T { + fn visit_with>(&self, visitor: &mut V) -> V::Result { + (**self).visit_with(visitor) + } +} + impl> TypeVisitable for Arc { fn visit_with>(&self, visitor: &mut V) -> V::Result { (**self).visit_with(visitor) @@ -363,6 +369,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/compiler/rustc_type_ir/src/walk.rs b/compiler/rustc_type_ir/src/walk.rs index 96ae6f1c06146..d18c37d237839 100644 --- a/compiler/rustc_type_ir/src/walk.rs +++ b/compiler/rustc_type_ir/src/walk.rs @@ -106,7 +106,7 @@ fn push_inner(stack: &mut TypeWalkerStack, parent: I::GenericArg stack.push(ty.into()); stack.push(lt.into()); } - ty::Alias(alias) => { + ty::Alias(_is_rigid, alias) => { stack.extend(alias.args.iter().rev()); } ty::Dynamic(obj, lt) => { @@ -160,7 +160,7 @@ fn push_inner(stack: &mut TypeWalkerStack, parent: I::GenericArg ty::ConstKind::Value(cv) => stack.push(cv.ty().into()), ty::ConstKind::Expr(expr) => stack.extend(expr.args().iter().rev()), - ty::ConstKind::Unevaluated(ct) => { + ty::ConstKind::Unevaluated(_is_rigid, ct) => { stack.extend(ct.args.iter().rev()); } }, diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs index 2cb98fdfe4484..a189bd7b717e9 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs @@ -139,7 +139,7 @@ fn is_ref_iterable<'tcx>( } let res_ty = cx.tcx.erase_and_anonymize_regions( - EarlyBinder::bind(req_res_ty) + EarlyBinder::bind(cx.tcx, req_res_ty) .instantiate(cx.tcx, typeck.node_args(call_expr.hir_id)) .skip_norm_wip(), ); diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index 4f281d745a94e..b7140a1b4f445 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -286,7 +286,7 @@ fn is_contains_sig(cx: &LateContext<'_>, call_id: HirId, iter_expr: &Expr<'_>) - .try_normalize_erasing_regions(cx.typing_env(), Unnormalized::new_wip(proj_ty)) { item_ty - == EarlyBinder::bind(search_ty) + == EarlyBinder::bind(cx.tcx, search_ty) .instantiate(cx.tcx, cx.typeck_results().node_args(call_id)) .skip_norm_wip() } else { diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs index f8fe6aa15d324..f723094fe7173 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -285,7 +285,7 @@ fn needless_borrow_count<'tcx>( return false; } - let predicate = EarlyBinder::bind(predicate) + let predicate = EarlyBinder::bind(cx.tcx, predicate) .instantiate(cx.tcx, &args_with_referent_ty[..]) .skip_norm_wip(); let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate); diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 22d7d83d730d9..34fa875c07fc1 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -384,7 +384,7 @@ impl<'tcx> NonCopyConst<'tcx> { e: &'tcx Expr<'tcx>, ) -> bool { // Make sure to instantiate all types coming from `typeck` with `gen_args`. - let ty = EarlyBinder::bind(typeck.expr_ty(e)).instantiate(tcx, gen_args); + let ty = EarlyBinder::bind(tcx, typeck.expr_ty(e)).instantiate(tcx, gen_args); let ty = tcx .try_normalize_erasing_regions(typing_env, ty) .unwrap_or(ty.skip_norm_wip()); @@ -401,7 +401,7 @@ impl<'tcx> NonCopyConst<'tcx> { }, ExprKind::Path(ref p) => { let res = typeck.qpath_res(p, e.hir_id); - let gen_args = EarlyBinder::bind(typeck.node_args(e.hir_id)) + let gen_args = EarlyBinder::bind(tcx, typeck.node_args(e.hir_id)) .instantiate(tcx, gen_args) .skip_norm_wip(); match res { @@ -599,7 +599,7 @@ impl<'tcx> NonCopyConst<'tcx> { init_expr = next_init; }, ExprKind::Path(ref init_path) => { - let next_init_args = EarlyBinder::bind(init_typeck.node_args(init_expr.hir_id)) + let next_init_args = EarlyBinder::bind(tcx, init_typeck.node_args(init_expr.hir_id)) .instantiate(tcx, init_args) .skip_norm_wip(); match init_typeck.qpath_res(init_path, init_expr.hir_id) { diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs index d6db088ba76c0..41d06a29d2c25 100644 --- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs +++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs @@ -112,7 +112,7 @@ fn into_iter_bound<'tcx>( } })); - let predicate = EarlyBinder::bind(tr).instantiate(cx.tcx, args).skip_norm_wip(); + let predicate = EarlyBinder::bind(cx.tcx, tr).instantiate(cx.tcx, args).skip_norm_wip(); let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate); if !cx .tcx diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index c208b8b97506f..e8342e691dbd4 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -3293,7 +3293,7 @@ fn get_path_to_ty<'tcx>(tcx: TyCtxt<'tcx>, from: LocalDefId, ty: Ty<'tcx>, args: | rustc_ty::RawPtr(_, _) | rustc_ty::Ref(..) | rustc_ty::Slice(_) - | rustc_ty::Tuple(_) => format!("<{}>", EarlyBinder::bind(ty).instantiate(tcx, args).skip_norm_wip()), + | rustc_ty::Tuple(_) => format!("<{}>", EarlyBinder::bind(tcx, ty).instantiate(tcx, args).skip_norm_wip()), _ => ty.to_string(), } } diff --git a/tests/mir-opt/issue_99325.main.built.after.32bit.mir b/tests/mir-opt/issue_99325.main.built.after.32bit.mir index 29fdccf85aa00..b57b9f22c8bb8 100644 --- a/tests/mir-opt/issue_99325.main.built.after.32bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.32bit.mir @@ -2,7 +2,7 @@ | User Type Annotations | 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { kind: Anon { def_id: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}) }, args: [], .. }], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { kind: Anon { def_id: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}) }, args: [], is_rigid: No, .. }], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/issue_99325.main.built.after.64bit.mir b/tests/mir-opt/issue_99325.main.built.after.64bit.mir index 29fdccf85aa00..b57b9f22c8bb8 100644 --- a/tests/mir-opt/issue_99325.main.built.after.64bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.64bit.mir @@ -2,7 +2,7 @@ | User Type Annotations | 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { kind: Anon { def_id: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}) }, args: [], .. }], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { kind: Anon { def_id: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}) }, args: [], is_rigid: No, .. }], user_self_ty: None }), max_universe: U0, var_kinds: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); diff --git a/tests/ui/associated-inherent-types/normalization-overflow.next.stderr b/tests/ui/associated-inherent-types/normalization-overflow.next.stderr index 5f0939b9f7763..69d087b0c7040 100644 --- a/tests/ui/associated-inherent-types/normalization-overflow.next.stderr +++ b/tests/ui/associated-inherent-types/normalization-overflow.next.stderr @@ -1,9 +1,9 @@ -error[E0271]: type mismatch resolving `T::This normalizes-to _` +error[E0275]: overflow evaluating the requirement `T::This == _` --> $DIR/normalization-overflow.rs:14:5 | LL | type This = Self::This; - | ^^^^^^^^^ types differ + | ^^^^^^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/associated-inherent-types/normalization-overflow.rs b/tests/ui/associated-inherent-types/normalization-overflow.rs index c5505578f4f00..7fcea9cb67029 100644 --- a/tests/ui/associated-inherent-types/normalization-overflow.rs +++ b/tests/ui/associated-inherent-types/normalization-overflow.rs @@ -13,7 +13,7 @@ struct T; impl T { type This = Self::This; //[current]~^ ERROR: overflow evaluating associated type `T::This` - //[next]~^^ ERROR: type mismatch resolving `T::This normalizes-to _` + //[next]~^^ ERROR: overflow evaluating the requirement `T::This == _` } fn main() {} diff --git a/tests/ui/assumptions_on_binders/alias_outlives.rs b/tests/ui/assumptions_on_binders/alias_outlives.rs index c234773fb10d8..a1e250152df4b 100644 --- a/tests/ui/assumptions_on_binders/alias_outlives.rs +++ b/tests/ui/assumptions_on_binders/alias_outlives.rs @@ -1,5 +1,7 @@ //@ compile-flags: -Znext-solver -Zassumptions-on-binders +// FIXME: Eagerly normalizing added goals probably makes the diagnostics worse. + // 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 :) @@ -20,14 +22,16 @@ where ::Assoc: 'static, { let _: ReqTrait; + //~^ ERROR: type annotations needed } fn borrowck_env_fail<'a, T: AliasHaver>() -//~^ ERROR: unsatisfied lifetime constraint from -Zassumptions-on-binders +// expected diagnostics: ERROR: unsatisfied lifetime constraint from -Zassumptions-on-binders where ::Assoc: 'a, { let _: ReqTrait; + //~^ ERROR: type annotations needed } const REGIONCK_ENV_PASS<'a, T: AliasHaver>: ReqTrait = todo!() diff --git a/tests/ui/assumptions_on_binders/alias_outlives.stderr b/tests/ui/assumptions_on_binders/alias_outlives.stderr index bd3819798737d..d8f7bf41e9c33 100644 --- a/tests/ui/assumptions_on_binders/alias_outlives.stderr +++ b/tests/ui/assumptions_on_binders/alias_outlives.stderr @@ -1,21 +1,23 @@ error: unsatisfied lifetime constraint from -Zassumptions-on-binders :3 - --> $DIR/alias_outlives.rs:37:1 + --> $DIR/alias_outlives.rs:41: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 +error[E0282]: type annotations needed + --> $DIR/alias_outlives.rs:24:12 | -LL | / fn borrowck_env_fail<'a, T: AliasHaver>() -LL | | -LL | | where -LL | | ::Assoc: 'a, - | |_________________________________^ +LL | let _: ReqTrait; + | ^^^^^^^^^^^^^^^^^^ cannot infer type for struct `ReqTrait<::Assoc>` + +error[E0282]: type annotations needed + --> $DIR/alias_outlives.rs:33:12 | - = note: meoow :c +LL | let _: ReqTrait; + | ^^^^^^^^^^^^^^^^^^ cannot infer type for struct `ReqTrait<::Assoc>` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0282`. 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 index c0cb6ce416aed..197966decc9ec 100644 --- 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 @@ -1,8 +1,10 @@ //@ compile-flags: -Znext-solver -Zassumptions-on-binders -//@ check-pass #![feature(generic_const_items)] +// FIXME: This should be `check-pass`. But eagerly normalizing added goals makes +// it fail. + // sorry for writing this // - boxy @@ -26,6 +28,7 @@ where trait InnerBinder<'a, 'b, 'c> {} impl<'a, 'b, 'c, S> InnerBinder<'a, 'b, 'c> for S +//~^ ERROR: type annotations needed: cannot satisfy `S: InnerBinder<'a, 'b, 'c>` where S: Trait<'a, 'b>, >::Assoc: 'c {} @@ -44,9 +47,12 @@ where T: for<'a, 'b> Trait<'a, 'b> { let _: ReqTrait<'c, T>; + //~^ ERROR: type annotations needed: cannot satisfy `for<'a, 'b> T: InnerBinder<'a, 'b, 'c>` } const REGIONCK_ENV<'c, T>: ReqTrait<'c, T> = todo!() +//~^ ERROR: type annotations needed: cannot satisfy `for<'a, 'b> T: InnerBinder<'a, 'b, 'c>` +//~| ERROR: type annotations needed: cannot satisfy `for<'a, 'b> T: InnerBinder<'a, 'b, 'c>` where T: for<'a, 'b> Trait<'a, 'b>; diff --git a/tests/ui/assumptions_on_binders/implied_higher_ranked_alias_outlives_assumption.stderr b/tests/ui/assumptions_on_binders/implied_higher_ranked_alias_outlives_assumption.stderr new file mode 100644 index 0000000000000..2c28794db5543 --- /dev/null +++ b/tests/ui/assumptions_on_binders/implied_higher_ranked_alias_outlives_assumption.stderr @@ -0,0 +1,123 @@ +error[E0283]: type annotations needed: cannot satisfy `S: InnerBinder<'a, 'b, 'c>` + --> $DIR/implied_higher_ranked_alias_outlives_assumption.rs:30:49 + | +LL | impl<'a, 'b, 'c, S> InnerBinder<'a, 'b, 'c> for S + | ^ + | + = note: cannot satisfy `S: InnerBinder<'a, 'b, 'c>` +help: the trait `InnerBinder<'a, 'b, 'c>` is not implemented for `S` + but trait `InnerBinder<'_, '_, '_>` is implemented for it + --> $DIR/implied_higher_ranked_alias_outlives_assumption.rs:30:1 + | +LL | / impl<'a, 'b, 'c, S> InnerBinder<'a, 'b, 'c> for S +LL | | +LL | | where +LL | | S: Trait<'a, 'b>, +LL | | >::Assoc: 'c {} + | |___________________________________^ + +error[E0283]: type annotations needed: cannot satisfy `for<'a, 'b> T: InnerBinder<'a, 'b, 'c>` + --> $DIR/implied_higher_ranked_alias_outlives_assumption.rs:53:28 + | +LL | const REGIONCK_ENV<'c, T>: ReqTrait<'c, T> = todo!() + | ^^^^^^^^^^^^^^^ + | + = note: cannot satisfy `for<'a, 'b> T: InnerBinder<'a, 'b, 'c>` +help: the trait `InnerBinder<'a, 'b, 'c>` is not implemented for `T` + but trait `InnerBinder<'_, '_, '_>` is implemented for it + --> $DIR/implied_higher_ranked_alias_outlives_assumption.rs:30:1 + | +LL | / impl<'a, 'b, 'c, S> InnerBinder<'a, 'b, 'c> for S +LL | | +LL | | where +LL | | S: Trait<'a, 'b>, +LL | | >::Assoc: 'c {} + | |___________________________________^ +note: required for `T` to implement `for<'a> OuterBinder<'a, 'c, ImpliedBound<'a, 'c, T>>` + --> $DIR/implied_higher_ranked_alias_outlives_assumption.rs:37:21 + | +LL | impl<'a, 'c, T0, S> OuterBinder<'a, 'c, T0> for S + | ^^^^^^^^^^^^^^^^^^^^^^^ ^ +LL | where +LL | for<'b> S: InnerBinder<'a, 'b, 'c>, {} + | ----------------------- unsatisfied trait bound introduced here +note: required by a bound in `ReqTrait` + --> $DIR/implied_higher_ranked_alias_outlives_assumption.rs:43:16 + | +LL | struct ReqTrait<'c, T>(&'c (), T) + | -------- required by a bound in this struct +LL | where +LL | for<'a> T: OuterBinder<'a, 'c, ImpliedBound<'a, 'c, T>>,; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ReqTrait` + +error[E0283]: type annotations needed: cannot satisfy `for<'a, 'b> T: InnerBinder<'a, 'b, 'c>` + --> $DIR/implied_higher_ranked_alias_outlives_assumption.rs:49:12 + | +LL | let _: ReqTrait<'c, T>; + | ^^^^^^^^^^^^^^^ + | + = note: cannot satisfy `for<'a, 'b> T: InnerBinder<'a, 'b, 'c>` +help: the trait `InnerBinder<'a, 'b, 'c>` is not implemented for `T` + but trait `InnerBinder<'_, '_, '_>` is implemented for it + --> $DIR/implied_higher_ranked_alias_outlives_assumption.rs:30:1 + | +LL | / impl<'a, 'b, 'c, S> InnerBinder<'a, 'b, 'c> for S +LL | | +LL | | where +LL | | S: Trait<'a, 'b>, +LL | | >::Assoc: 'c {} + | |___________________________________^ +note: required for `T` to implement `for<'a> OuterBinder<'a, 'c, ImpliedBound<'a, 'c, T>>` + --> $DIR/implied_higher_ranked_alias_outlives_assumption.rs:37:21 + | +LL | impl<'a, 'c, T0, S> OuterBinder<'a, 'c, T0> for S + | ^^^^^^^^^^^^^^^^^^^^^^^ ^ +LL | where +LL | for<'b> S: InnerBinder<'a, 'b, 'c>, {} + | ----------------------- unsatisfied trait bound introduced here +note: required by a bound in `ReqTrait` + --> $DIR/implied_higher_ranked_alias_outlives_assumption.rs:43:16 + | +LL | struct ReqTrait<'c, T>(&'c (), T) + | -------- required by a bound in this struct +LL | where +LL | for<'a> T: OuterBinder<'a, 'c, ImpliedBound<'a, 'c, T>>,; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ReqTrait` + +error[E0283]: type annotations needed: cannot satisfy `for<'a, 'b> T: InnerBinder<'a, 'b, 'c>` + --> $DIR/implied_higher_ranked_alias_outlives_assumption.rs:53:46 + | +LL | const REGIONCK_ENV<'c, T>: ReqTrait<'c, T> = todo!() + | ^^^^^^^ + | + = note: cannot satisfy `for<'a, 'b> T: InnerBinder<'a, 'b, 'c>` +help: the trait `InnerBinder<'a, 'b, 'c>` is not implemented for `T` + but trait `InnerBinder<'_, '_, '_>` is implemented for it + --> $DIR/implied_higher_ranked_alias_outlives_assumption.rs:30:1 + | +LL | / impl<'a, 'b, 'c, S> InnerBinder<'a, 'b, 'c> for S +LL | | +LL | | where +LL | | S: Trait<'a, 'b>, +LL | | >::Assoc: 'c {} + | |___________________________________^ +note: required for `T` to implement `for<'a> OuterBinder<'a, 'c, ImpliedBound<'a, 'c, T>>` + --> $DIR/implied_higher_ranked_alias_outlives_assumption.rs:37:21 + | +LL | impl<'a, 'c, T0, S> OuterBinder<'a, 'c, T0> for S + | ^^^^^^^^^^^^^^^^^^^^^^^ ^ +LL | where +LL | for<'b> S: InnerBinder<'a, 'b, 'c>, {} + | ----------------------- unsatisfied trait bound introduced here +note: required by a bound in `ReqTrait` + --> $DIR/implied_higher_ranked_alias_outlives_assumption.rs:43:16 + | +LL | struct ReqTrait<'c, T>(&'c (), T) + | -------- required by a bound in this struct +LL | where +LL | for<'a> T: OuterBinder<'a, 'c, ImpliedBound<'a, 'c, T>>,; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ReqTrait` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/attributes/dump-preds.stderr b/tests/ui/attributes/dump-preds.stderr index 12d9308431734..bf6d161a25f41 100644 --- a/tests/ui/attributes/dump-preds.stderr +++ b/tests/ui/attributes/dump-preds.stderr @@ -33,7 +33,7 @@ error: rustc_dump_item_bounds LL | type Assoc: std::ops::Deref | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: Binder { value: ProjectionPredicate(AliasTerm { args: [Alias(AliasTy { args: [Self/#0, T/#1, P/#2], kind: Projection { def_id: DefId(..) }, .. })], kind: ProjectionTy { def_id: DefId(..) }, .. }, Term::Ty(())), bound_vars: [] } + = note: Binder { value: ProjectionPredicate(AliasTerm { args: [Alias(No, AliasTy { args: [Self/#0, T/#1, P/#2], kind: Projection { def_id: DefId(..) }, .. })], kind: ProjectionTy { def_id: DefId(..) }, .. }, Term::Ty(())), bound_vars: [] } = note: Binder { value: TraitPredicate(<>::Assoc

as std::ops::Deref>, polarity:Positive), bound_vars: [] } = note: Binder { value: TraitPredicate(<>::Assoc

as std::marker::Sized>, polarity:Positive), bound_vars: [] } diff --git a/tests/ui/const-generics/gca/non-type-equality-fail.stderr b/tests/ui/const-generics/gca/non-type-equality-fail.stderr index 796efdcea93cc..05d90f5632728 100644 --- a/tests/ui/const-generics/gca/non-type-equality-fail.stderr +++ b/tests/ui/const-generics/gca/non-type-equality-fail.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | let _: Struct<{ as Trait>::PROJECTED_A }> = | -------------------------------------------------------- expected due to this LL | Struct::<{ as Trait>::PROJECTED_B }>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected ` as Trait>::PROJECTED_A`, found ` as Trait>::PROJECTED_B` | = note: expected struct `Struct< as Trait>::PROJECTED_A>` found struct `Struct< as Trait>::PROJECTED_B>` @@ -13,7 +13,7 @@ error[E0308]: mismatched types --> $DIR/non-type-equality-fail.rs:37:41 | LL | let _: Struct<{ T::PROJECTED_A }> = Struct::<{ T::PROJECTED_B }>; - | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + | -------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `::PROJECTED_A`, found `::PROJECTED_B` | | | expected due to this | diff --git a/tests/ui/const-generics/mgca/free-const-recursive.rs b/tests/ui/const-generics/mgca/free-const-recursive.rs index 8d75c1a941a77..6219bf6c0fba9 100644 --- a/tests/ui/const-generics/mgca/free-const-recursive.rs +++ b/tests/ui/const-generics/mgca/free-const-recursive.rs @@ -5,8 +5,9 @@ #![expect(incomplete_features)] type const A: () = A; -//~^ ERROR type mismatch resolving `A normalizes-to _` -//~| ERROR the constant `A` is not of type `()` +//~^ ERROR: overflow evaluating the requirement `A == _` +//~| ERROR: overflow evaluating the requirement `A == _` +//~| ERROR: type annotations needed 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..1026755abe6c9 100644 --- a/tests/ui/const-generics/mgca/free-const-recursive.stderr +++ b/tests/ui/const-generics/mgca/free-const-recursive.stderr @@ -1,15 +1,24 @@ -error[E0271]: type mismatch resolving `A normalizes-to _` +error[E0275]: overflow evaluating the requirement `A == _` --> $DIR/free-const-recursive.rs:7:1 | LL | type const A: () = A; - | ^^^^^^^^^^^^^^^^ types differ + | ^^^^^^^^^^^^^^^^ -error: the constant `A` is not of type `()` +error[E0275]: overflow evaluating the requirement `A == _` --> $DIR/free-const-recursive.rs:7:1 | LL | type const A: () = A; - | ^^^^^^^^^^^^^^^^ expected `()`, found a different `()` + | ^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0284]: type annotations needed + --> $DIR/free-const-recursive.rs:7:1 + | +LL | type const A: () = A; + | ^^^^^^^^^^^^^^^^ cannot infer the value of the constant `_` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0275, E0284. +For more information about an error, try `rustc --explain E0275`. diff --git a/tests/ui/const-generics/mgca/projection-const-recursive.rs b/tests/ui/const-generics/mgca/projection-const-recursive.rs index c9b5039b5fd0b..5b1c8b3d945cc 100644 --- a/tests/ui/const-generics/mgca/projection-const-recursive.rs +++ b/tests/ui/const-generics/mgca/projection-const-recursive.rs @@ -10,8 +10,9 @@ 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: overflow evaluating the requirement `<() as Trait>::A == _` + //~| ERROR: overflow evaluating the requirement `<() as Trait>::A == _` + //~| ERROR: type annotations needed } 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..6d68dea41d63f 100644 --- a/tests/ui/const-generics/mgca/projection-const-recursive.stderr +++ b/tests/ui/const-generics/mgca/projection-const-recursive.stderr @@ -1,15 +1,24 @@ -error[E0271]: type mismatch resolving `<() as Trait>::A normalizes-to _` +error[E0275]: overflow evaluating the requirement `<() as Trait>::A == _` --> $DIR/projection-const-recursive.rs:12:5 | LL | type const A: () = <() as Trait>::A; - | ^^^^^^^^^^^^^^^^ types differ + | ^^^^^^^^^^^^^^^^ -error: the constant `<() as Trait>::A` is not of type `()` +error[E0275]: overflow evaluating the requirement `<() as Trait>::A == _` --> $DIR/projection-const-recursive.rs:12:5 | LL | type const A: () = <() as Trait>::A; - | ^^^^^^^^^^^^^^^^ expected `()`, found a different `()` + | ^^^^^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0284]: type annotations needed + --> $DIR/projection-const-recursive.rs:12:5 + | +LL | type const A: () = <() as Trait>::A; + | ^^^^^^^^^^^^^^^^ cannot infer the value of the constant `_` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0271`. +Some errors have detailed explanations: E0275, E0284. +For more information about an error, try `rustc --explain E0275`. diff --git a/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs index 2332c97a70ee8..c468e6d990a12 100644 --- a/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs +++ b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs @@ -4,6 +4,7 @@ type const X: usize = const { N }; //~^ ERROR type annotations needed +//~| ERROR type annotations needed type const N: usize = "this isn't a usize"; //~^ ERROR the constant `"this isn't a usize"` is not of type `usize` diff --git a/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.stderr b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.stderr index 482a241b43c75..f72a14ab3e8f7 100644 --- a/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.stderr +++ b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.stderr @@ -4,12 +4,18 @@ error[E0284]: type annotations needed: cannot normalize `X::{constant#0}` LL | type const X: usize = const { N }; | ^^^^^^^^^^^^^^^^^^^ cannot normalize `X::{constant#0}` +error[E0284]: type annotations needed + --> $DIR/type-const-free-anon-const-mismatch.rs:5:1 + | +LL | type const X: usize = const { N }; + | ^^^^^^^^^^^^^^^^^^^ cannot infer the value of the constant `_` + error: the constant `"this isn't a usize"` is not of type `usize` - --> $DIR/type-const-free-anon-const-mismatch.rs:8:1 + --> $DIR/type-const-free-anon-const-mismatch.rs:9:1 | LL | type const N: usize = "this isn't a usize"; | ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&'static str` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0284`. 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..84d1d06234111 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/infinite/infinite-type-alias-mutual-recursion.feature_new.stderr b/tests/ui/infinite/infinite-type-alias-mutual-recursion.feature_new.stderr index 1d6ace580951b..8375055929ce8 100644 --- a/tests/ui/infinite/infinite-type-alias-mutual-recursion.feature_new.stderr +++ b/tests/ui/infinite/infinite-type-alias-mutual-recursion.feature_new.stderr @@ -1,21 +1,21 @@ -error[E0271]: type mismatch resolving `X3 normalizes-to _` +error[E0275]: overflow evaluating the requirement `X2 == _` --> $DIR/infinite-type-alias-mutual-recursion.rs:12:1 | LL | type X1 = X2; - | ^^^^^^^ types differ + | ^^^^^^^ -error[E0271]: type mismatch resolving `X1 normalizes-to _` +error[E0275]: overflow evaluating the requirement `X3 == _` --> $DIR/infinite-type-alias-mutual-recursion.rs:16:1 | LL | type X2 = X3; - | ^^^^^^^ types differ + | ^^^^^^^ -error[E0271]: type mismatch resolving `X2 normalizes-to _` +error[E0275]: overflow evaluating the requirement `X1 == _` --> $DIR/infinite-type-alias-mutual-recursion.rs:19:1 | LL | type X3 = X1; - | ^^^^^^^ types differ + | ^^^^^^^ error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/infinite/infinite-type-alias-mutual-recursion.rs b/tests/ui/infinite/infinite-type-alias-mutual-recursion.rs index 24e1318ca3d7d..f876253b42b5f 100644 --- a/tests/ui/infinite/infinite-type-alias-mutual-recursion.rs +++ b/tests/ui/infinite/infinite-type-alias-mutual-recursion.rs @@ -12,12 +12,12 @@ type X1 = X2; //[gated_old,gated_new]~^ ERROR cycle detected when expanding type alias `X1` //[feature_old]~^^ ERROR: overflow normalizing the type alias `X2` -//[feature_new]~^^^ ERROR: type mismatch resolving `X3 normalizes-to _` +//[feature_new]~^^^ ERROR: overflow evaluating the requirement `X2 == _` type X2 = X3; //[feature_old]~^ ERROR: overflow normalizing the type alias `X3` -//[feature_new]~^^ ERROR: type mismatch resolving `X1 normalizes-to _` +//[feature_new]~^^ ERROR: overflow evaluating the requirement `X3 == _` type X3 = X1; //[feature_old]~^ ERROR: overflow normalizing the type alias `X1` -//[feature_new]~^^ ERROR: type mismatch resolving `X2 normalizes-to _` +//[feature_new]~^^ ERROR: overflow evaluating the requirement `X1 == _` fn main() {} diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr index a592d3537ebde..dbd982ea94c36 100644 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr +++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr @@ -1,20 +1,20 @@ -error[E0271]: type mismatch resolving `Loop normalizes-to _` +error[E0275]: overflow evaluating the requirement `Loop == _` --> $DIR/inherent-impls-overflow.rs:8:1 | LL | type Loop = Loop; - | ^^^^^^^^^ types differ + | ^^^^^^^^^ -error[E0271]: type mismatch resolving `Loop normalizes-to _` +error[E0275]: overflow evaluating the requirement `Loop == _` --> $DIR/inherent-impls-overflow.rs:12:1 | LL | impl Loop {} - | ^^^^^^^^^^^^ types differ + | ^^^^^^^^^^^^ -error[E0271]: type mismatch resolving `Loop normalizes-to _` +error[E0275]: overflow evaluating the requirement `Loop == _` --> $DIR/inherent-impls-overflow.rs:12:6 | LL | impl Loop {} - | ^^^^ types differ + | ^^^^ error[E0275]: overflow evaluating the requirement `Poly1<(T,)> == _` --> $DIR/inherent-impls-overflow.rs:17:1 @@ -50,5 +50,4 @@ LL | impl Poly0<()> {} error: aborting due to 7 previous errors -Some errors have detailed explanations: E0271, E0275. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs index be3cda4d53584..66a81321624b0 100644 --- a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs +++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs @@ -7,12 +7,12 @@ type Loop = Loop; //[current]~^ ERROR overflow normalizing the type alias `Loop` -//[next]~^^ ERROR type mismatch resolving `Loop normalizes-to _` +//[next]~^^ ERROR overflow evaluating the requirement `Loop == _` impl Loop {} //[current]~^ ERROR overflow normalizing the type alias `Loop` -//[next]~^^ ERROR type mismatch resolving `Loop normalizes-to _` -//[next]~| ERROR type mismatch resolving `Loop normalizes-to _` +//[next]~^^ ERROR overflow evaluating the requirement `Loop == _` +//[next]~| ERROR overflow evaluating the requirement `Loop == _` type Poly0 = Poly1<(T,)>; //[current]~^ ERROR overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>` diff --git a/tests/ui/methods/rigid-alias-bound-is-not-inherent.next.stderr b/tests/ui/methods/rigid-alias-bound-is-not-inherent.next.stderr index afacb3a7d5213..4652bf5e3c586 100644 --- a/tests/ui/methods/rigid-alias-bound-is-not-inherent.next.stderr +++ b/tests/ui/methods/rigid-alias-bound-is-not-inherent.next.stderr @@ -9,7 +9,7 @@ note: candidate #1 is defined in the trait `Trait1` | LL | fn method(&self) { | ^^^^^^^^^^^^^^^^ -note: candidate #2 is defined in the trait `Trait2` +note: candidate #2 is defined in an impl of the trait `Trait2` for the type `T` --> $DIR/rigid-alias-bound-is-not-inherent.rs:27:5 | LL | fn method(&self) { diff --git a/tests/ui/offset-of/inside-array-length.stderr b/tests/ui/offset-of/inside-array-length.stderr index fd47e6c8b6805..dba4fd08e89b4 100644 --- a/tests/ui/offset-of/inside-array-length.stderr +++ b/tests/ui/offset-of/inside-array-length.stderr @@ -37,7 +37,7 @@ LL | fn foo<'a, T: 'a>(_: [(); std::mem::offset_of!((T,), 0)]) {} = note: ...which requires caching mir of `foo::{constant#0}` for CTFE... = note: ...which requires elaborating drops for `foo::{constant#0}`... = note: ...which requires borrow-checking `foo::{constant#0}`... - = note: ...which requires normalizing `Binder { value: ConstEvaluatable(UnevaluatedConst { kind: Anon { def_id: DefId(0:7 ~ inside_array_length[07d6]::foo::{constant#0}) }, args: ['^c_1, T/#1], .. }), bound_vars: [] }`... + = note: ...which requires normalizing `Binder { value: ConstEvaluatable(Unevaluated(No, UnevaluatedConst { kind: Anon { def_id: DefId(0:7 ~ inside_array_length[07d6]::foo::{constant#0}) }, args: ['^c_1, T/#1], .. })), bound_vars: [] }`... = note: ...which again requires evaluating type-level constant, completing the cycle = note: cycle used when normalizing `inside_array_length::::foo::{constant#0}` = note: for more information, see and diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-4.next.stderr b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-4.next.stderr index c7d774644c2ba..effab17e8c3bc 100644 --- a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-4.next.stderr +++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-4.next.stderr @@ -1,9 +1,9 @@ -error[E0284]: type annotations needed: cannot normalize `>::Type` - --> $DIR/ambiguity-due-to-uniquification-4.rs:17:44 +error[E0282]: type annotations needed + --> $DIR/ambiguity-due-to-uniquification-4.rs:17:47 | LL | pub fn f<'a, 'b, T: Trait<'a> + Trait<'b>>(v: >::Type) {} - | ^ cannot normalize `>::Type` + | ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for associated type `>::Type` error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0284`. +For more information about this error, try `rustc --explain E0282`. 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..c9a3eaa0fea52 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/normalize/dont-ice-on-normalization-failure.rs b/tests/ui/traits/next-solver/normalize/dont-ice-on-normalization-failure.rs index 302c48d173566..bb76f0d5aff95 100644 --- a/tests/ui/traits/next-solver/normalize/dont-ice-on-normalization-failure.rs +++ b/tests/ui/traits/next-solver/normalize/dont-ice-on-normalization-failure.rs @@ -13,7 +13,7 @@ type TraitObject = dyn Generic<::Associated>; //~^ ERROR: the trait bound `i32: Trait` is not satisfied struct Wrap(TraitObject); -//~^ ERROR: the trait bound `i32: Trait` is not satisfied +//~^ ERROR: type mismatch resolving `TraitObject normalizes-to _` fn cast(x: *mut Wrap) { x as *mut Wrap; diff --git a/tests/ui/traits/next-solver/normalize/dont-ice-on-normalization-failure.stderr b/tests/ui/traits/next-solver/normalize/dont-ice-on-normalization-failure.stderr index 5e857df955adf..4aacc281f7fe4 100644 --- a/tests/ui/traits/next-solver/normalize/dont-ice-on-normalization-failure.stderr +++ b/tests/ui/traits/next-solver/normalize/dont-ice-on-normalization-failure.stderr @@ -10,18 +10,13 @@ help: this trait has no implementations, consider adding one LL | trait Trait { | ^^^^^^^^^^^ -error[E0277]: the trait bound `i32: Trait` is not satisfied +error[E0271]: type mismatch resolving `TraitObject normalizes-to _` --> $DIR/dont-ice-on-normalization-failure.rs:15:13 | LL | struct Wrap(TraitObject); - | ^^^^^^^^^^^ the trait `Trait` is not implemented for `i32` - | -help: this trait has no implementations, consider adding one - --> $DIR/dont-ice-on-normalization-failure.rs:6:1 - | -LL | trait Trait { - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ types differ error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0271, E0277. +For more information about an error, try `rustc --explain E0271`. 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/stalled-coroutine-obligations.rs b/tests/ui/traits/next-solver/stalled-coroutine-obligations.rs index 5e5bc0a39f6a5..7076b0741e265 100644 --- a/tests/ui/traits/next-solver/stalled-coroutine-obligations.rs +++ b/tests/ui/traits/next-solver/stalled-coroutine-obligations.rs @@ -16,11 +16,11 @@ fn stalled_copy_clone() { type T = impl Copy; let foo: T = async {}; - //~^ ERROR: the trait bound + //~^ ERROR: type mismatch resolving `T normalizes-to _` type U = impl Clone; let bar: U = async {}; - //~^ ERROR: the trait bound + //~^ ERROR: type mismatch resolving `U normalizes-to _` } auto trait Valid {} @@ -31,13 +31,13 @@ fn stalled_auto_traits() { type T = impl Valid; let a = False; let foo: T = async { a }; - //~^ ERROR: the trait bound `False: Valid` is not satisfied + //~^ ERROR: type mismatch resolving `T normalizes-to _` } trait Trait { fn stalled_send(&self, b: *mut ()) -> impl Future + Send { - //~^ ERROR: type mismatch resolving + //~^ ERROR: type mismatch resolving `impl Future + Send == {async block async move { b } diff --git a/tests/ui/traits/next-solver/stalled-coroutine-obligations.stderr b/tests/ui/traits/next-solver/stalled-coroutine-obligations.stderr index 0a01803e2168e..bda1e0455e962 100644 --- a/tests/ui/traits/next-solver/stalled-coroutine-obligations.stderr +++ b/tests/ui/traits/next-solver/stalled-coroutine-obligations.stderr @@ -1,33 +1,20 @@ -error[E0277]: the trait bound `{async block@$DIR/stalled-coroutine-obligations.rs:18:18: 18:23}: Copy` is not satisfied +error[E0271]: type mismatch resolving `T normalizes-to _` --> $DIR/stalled-coroutine-obligations.rs:18:14 | LL | let foo: T = async {}; - | ^ the trait `Copy` is not implemented for `{async block@$DIR/stalled-coroutine-obligations.rs:18:18: 18:23}` + | ^ types differ -error[E0277]: the trait bound `{async block@$DIR/stalled-coroutine-obligations.rs:22:18: 22:23}: Clone` is not satisfied +error[E0271]: type mismatch resolving `U normalizes-to _` --> $DIR/stalled-coroutine-obligations.rs:22:14 | LL | let bar: U = async {}; - | ^ the trait `Clone` is not implemented for `{async block@$DIR/stalled-coroutine-obligations.rs:22:18: 22:23}` + | ^ types differ -error[E0277]: the trait bound `False: Valid` is not satisfied in `{async block@$DIR/stalled-coroutine-obligations.rs:33:18: 33:23}` +error[E0271]: type mismatch resolving `T normalizes-to _` --> $DIR/stalled-coroutine-obligations.rs:33:14 | LL | let foo: T = async { a }; - | ^ ----- within this `{async block@$DIR/stalled-coroutine-obligations.rs:33:18: 33:23}` - | | - | unsatisfied trait bound - | -help: within `{async block@$DIR/stalled-coroutine-obligations.rs:33:18: 33:23}`, the trait `Valid` is not implemented for `False` - --> $DIR/stalled-coroutine-obligations.rs:27:1 - | -LL | struct False; - | ^^^^^^^^^^^^ -note: captured value does not implement `Valid` - --> $DIR/stalled-coroutine-obligations.rs:33:26 - | -LL | let foo: T = async { a }; - | ^ has type `False` which does not implement `Valid` + | ^ types differ error[E0271]: type mismatch resolving `impl Future + Send == {async block@$DIR/stalled-coroutine-obligations.rs:41:9: 41:19}` --> $DIR/stalled-coroutine-obligations.rs:39:43 @@ -37,5 +24,4 @@ LL | fn stalled_send(&self, b: *mut ()) -> impl Future + Send { error: aborting due to 4 previous errors -Some errors have detailed explanations: E0271, E0277. -For more information about an error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0271`. 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..2826858f7048b 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 @@ -1,18 +1,15 @@ -error[E0271]: type mismatch resolving `::Diverges normalizes-to _` +error[E0275]: overflow evaluating the requirement `::Diverges == _` --> $DIR/normalize-diverging-alias-in-struct.rs:21:12 | LL | field: Box<::Diverges>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0271]: type mismatch resolving `::Diverges normalizes-to _` +error[E0275]: overflow evaluating whether `Box<::Diverges>` is 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 -For more information about this error, try `rustc --explain E0271`. +For more information about this error, try `rustc --explain E0275`. 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..17f57374a0da2 100644 --- a/tests/ui/traits/normalize/normalize-diverging-alias-in-struct.rs +++ b/tests/ui/traits/normalize/normalize-diverging-alias-in-struct.rs @@ -19,9 +19,8 @@ impl Trait for T { 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 _` + //~^ ERROR: overflow evaluating the requirement `::Diverges == _` + //[next]~^^ ERROR: overflow evaluating whether `Box<::Diverges>` is well-formed } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/coherence/coherence_different_hidden_ty.rs b/tests/ui/type-alias-impl-trait/coherence/coherence_different_hidden_ty.rs index 22dbdb28d8ba5..66442ac874516 100644 --- a/tests/ui/type-alias-impl-trait/coherence/coherence_different_hidden_ty.rs +++ b/tests/ui/type-alias-impl-trait/coherence/coherence_different_hidden_ty.rs @@ -9,6 +9,7 @@ // @lcnr: Because of this I decided to not bother and cause this to fail instead. // In the future we can definitely modify the compiler to accept this // again. + #![feature(type_alias_impl_trait)] trait Trait {} @@ -18,7 +19,7 @@ type TAIT = impl Sized; impl Trait for (TAIT, TAIT) {} impl Trait for (u32, i32) {} -//~^ ERROR: conflicting implementations of trait `Trait` for type +//~^ ERROR: conflicting implementations of trait `Trait` for type `(TAIT, TAIT)` #[define_opaque(TAIT)] fn define() -> TAIT {} diff --git a/tests/ui/type-alias-impl-trait/coherence/coherence_different_hidden_ty.stderr b/tests/ui/type-alias-impl-trait/coherence/coherence_different_hidden_ty.stderr index ef170101b4455..d7f6606d2099a 100644 --- a/tests/ui/type-alias-impl-trait/coherence/coherence_different_hidden_ty.stderr +++ b/tests/ui/type-alias-impl-trait/coherence/coherence_different_hidden_ty.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait` for type `(TAIT, TAIT)` - --> $DIR/coherence_different_hidden_ty.rs:20:1 + --> $DIR/coherence_different_hidden_ty.rs:21:1 | LL | impl Trait for (TAIT, TAIT) {} | --------------------------- first implementation here diff --git a/tests/ui/type-alias-impl-trait/const_eval_reveal_opaque_in_param_env.rs b/tests/ui/type-alias-impl-trait/const_eval_reveal_opaque_in_param_env.rs new file mode 100644 index 0000000000000..c2c04ce22f782 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/const_eval_reveal_opaque_in_param_env.rs @@ -0,0 +1,32 @@ +//@ edition: 2024 +//@ compile-flags: -Znext-solver -Zdisable-fast-paths +//@ check-pass + +// Test whether we mark the rigid alias in hir typeck non-rigid in const eval +// where we reveal all hidden types with `PostAnalysis` typing mode. +// +// This shouldn't compile as we shouldn't do const eval in non-empty param env +// in the future. + +#![feature(type_alias_impl_trait)] +type Tait = impl Sized; +#[define_opaque(Tait)] +fn foo(x: T) -> Tait { + x +} + +trait Trait { + type Assoc; +} + +fn bar() -> [u8; 4] +where + T: Trait, + Tait: Trait, +{ + [0; std::mem::size_of::<::Assoc>()] + //~^ WARN: cannot use constants which depend on generic parameters in types + //~| WARN: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/const_eval_reveal_opaque_in_param_env.stderr b/tests/ui/type-alias-impl-trait/const_eval_reveal_opaque_in_param_env.stderr new file mode 100644 index 0000000000000..e724327ea060d --- /dev/null +++ b/tests/ui/type-alias-impl-trait/const_eval_reveal_opaque_in_param_env.stderr @@ -0,0 +1,12 @@ +warning: cannot use constants which depend on generic parameters in types + --> $DIR/const_eval_reveal_opaque_in_param_env.rs:27:9 + | +LL | [0; std::mem::size_of::<::Assoc>()] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #76200 + = note: `#[warn(const_evaluatable_unchecked)]` (part of `#[warn(future_incompatible)]`) on by default + +warning: 1 warning emitted + 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..c597ccdab00df 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 {} }