diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index fda96dde8269d..7ca07bb9b4348 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -438,7 +438,7 @@ impl<'tcx> BorrowExplanation<'tcx> { let elaborated_args = std::iter::zip(*args, &generics.own_params).map(|(arg, param)| { - if let Some(ty::Dynamic(obj, _, ty::Dyn)) = arg.as_type().map(Ty::kind) { + if let Some(ty::Dynamic(obj, _)) = arg.as_type().map(Ty::kind) { let default = tcx.object_lifetime_default(param.def_id); let re_static = tcx.lifetimes.re_static; @@ -464,7 +464,7 @@ impl<'tcx> BorrowExplanation<'tcx> { has_dyn = true; - Ty::new_dynamic(tcx, obj, implied_region, ty::Dyn).into() + Ty::new_dynamic(tcx, obj, implied_region).into() } else { arg } diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 5d2dda8b0e7cc..5b20c5536c390 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -1904,7 +1904,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { | ty::Slice(_) | ty::FnDef(_, _) | ty::FnPtr(..) - | ty::Dynamic(_, _, _) + | ty::Dynamic(_, _) | ty::Closure(_, _) | ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) @@ -1950,7 +1950,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> { | ty::Ref(_, _, _) | ty::FnDef(_, _) | ty::FnPtr(..) - | ty::Dynamic(_, _, _) + | ty::Dynamic(_, _) | ty::CoroutineWitness(..) | ty::Never | ty::UnsafeBinder(_) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 8c5447fe1e9e7..8e6150fe9da2c 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1487,9 +1487,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { unsize_to: None, }, ); - } else if let ty::Dynamic(src_tty, _src_lt, ty::Dyn) = + } else if let ty::Dynamic(src_tty, _src_lt) = *self.struct_tail(src.ty, location).kind() - && let ty::Dynamic(dst_tty, dst_lt, ty::Dyn) = + && let ty::Dynamic(dst_tty, dst_lt) = *self.struct_tail(dst.ty, location).kind() && src_tty.principal().is_some() && dst_tty.principal().is_some() @@ -1511,7 +1511,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { // FIXME: Once we disallow casting `*const dyn Trait + 'short` // to `*const dyn Trait + 'long`, then this can just be `src_lt`. dst_lt, - ty::Dyn, ); let dst_obj = Ty::new_dynamic( tcx, @@ -1519,7 +1518,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { &dst_tty.without_auto_traits().collect::>(), ), dst_lt, - ty::Dyn, ); debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj); diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs index 7d0731c77bdc4..29ee46194de19 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs @@ -715,7 +715,7 @@ pub(crate) fn codegen_drop<'tcx>( fx.bcx.ins().jump(ret_block, &[]); } else { match ty.kind() { - ty::Dynamic(_, _, ty::Dyn) => { + ty::Dynamic(_, _) => { // IN THIS ARM, WE HAVE: // ty = *mut (dyn Trait) // which is: exists ( *mut T, Vtable ) diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs index 2aee0b2e97424..643c7feb89a26 100644 --- a/compiler/rustc_codegen_cranelift/src/unsize.rs +++ b/compiler/rustc_codegen_cranelift/src/unsize.rs @@ -30,9 +30,7 @@ pub(crate) fn unsized_info<'tcx>( fx.pointer_type, len.try_to_target_usize(fx.tcx).expect("expected monomorphic const in codegen") as i64, ), - (&ty::Dynamic(data_a, _, src_dyn_kind), &ty::Dynamic(data_b, _, target_dyn_kind)) - if src_dyn_kind == target_dyn_kind => - { + (&ty::Dynamic(data_a, _), &ty::Dynamic(data_b, _)) => { let old_info = old_info.expect("unsized_info: missing old info for trait upcasting coercion"); let b_principal_def_id = data_b.principal_def_id(); diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index 9d73f200afe2b..4519fa1a270e4 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -909,8 +909,7 @@ pub(crate) fn assert_assignable<'tcx>( ); // fn(&T) -> for<'l> fn(&'l T) is allowed } - (&ty::Dynamic(from_traits, _, _from_kind), &ty::Dynamic(to_traits, _, _to_kind)) => { - // FIXME(dyn-star): Do the right thing with DynKinds + (&ty::Dynamic(from_traits, _), &ty::Dynamic(to_traits, _)) => { for (from, to) in from_traits.iter().zip(to_traits) { let from = fx.tcx.normalize_erasing_late_bound_regions(fx.typing_env(), from); let to = fx.tcx.normalize_erasing_late_bound_regions(fx.typing_env(), to); diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 45b028aa8eff2..68a2f43ec67bc 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -168,9 +168,7 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( (&ty::Array(_, len), &ty::Slice(_)) => cx.const_usize( len.try_to_target_usize(cx.tcx()).expect("expected monomorphic const in codegen"), ), - (&ty::Dynamic(data_a, _, src_dyn_kind), &ty::Dynamic(data_b, _, target_dyn_kind)) - if src_dyn_kind == target_dyn_kind => - { + (&ty::Dynamic(data_a, _), &ty::Dynamic(data_b, _)) => { let old_info = old_info.expect("unsized_info: missing old info for trait upcasting coercion"); let b_principal_def_id = data_b.principal_def_id(); @@ -208,7 +206,7 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( old_info } } - (_, ty::Dynamic(data, _, _)) => meth::get_vtable( + (_, ty::Dynamic(data, _)) => meth::get_vtable( cx, source, data.principal() diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs index 34ad35a729b98..2fa466b500179 100644 --- a/compiler/rustc_codegen_ssa/src/meth.rs +++ b/compiler/rustc_codegen_ssa/src/meth.rs @@ -78,7 +78,7 @@ fn dyn_trait_in_self<'tcx>( ) -> Option> { for arg in ty.peel_refs().walk() { if let GenericArgKind::Type(ty) = arg.kind() - && let ty::Dynamic(data, _, _) = ty.kind() + && let ty::Dynamic(data, _) = ty.kind() { // FIXME(arbitrary_self_types): This is likely broken for receivers which // have a "non-self" trait objects as a generic argument. diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 6492ef73956b0..1b218a0d33956 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -614,7 +614,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let (maybe_null, drop_fn, fn_abi, drop_instance) = match ty.kind() { // FIXME(eddyb) perhaps move some of this logic into // `Instance::resolve_drop_in_place`? - ty::Dynamic(_, _, ty::Dyn) => { + ty::Dynamic(_, _) => { // IN THIS ARM, WE HAVE: // ty = *mut (dyn Trait) // which is: exists ( *mut T, Vtable ) diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 4cb88d44e1b11..23e4a2921ea6e 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -658,7 +658,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let val = self.read_immediate(&receiver)?; break self.ref_to_mplace(&val)?; } - ty::Dynamic(.., ty::Dyn) => break receiver.assert_mem_place(), // no immediate unsized values + ty::Dynamic(..) => break receiver.assert_mem_place(), // no immediate unsized values _ => { // Not there yet, search for the only non-ZST field. // (The rules for `DispatchFromDyn` ensure there's exactly one such field.) @@ -675,7 +675,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // (For that reason we also cannot use `unpack_dyn_trait`.) let receiver_tail = self.tcx.struct_tail_for_codegen(receiver_place.layout.ty, self.typing_env); - let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else { + let ty::Dynamic(receiver_trait, _) = receiver_tail.kind() else { span_bug!(self.cur_span(), "dynamic call on non-`dyn` type {}", receiver_tail) }; assert!(receiver_place.layout.is_unsized()); @@ -822,7 +822,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // instead we do the virtual call stuff ourselves. It's easier here than in `eval_fn_call` // since we can just get a place of the underlying type and use `mplace_to_ref`. let place = match place.layout.ty.kind() { - ty::Dynamic(data, _, ty::Dyn) => { + ty::Dynamic(data, _) => { // Dropping a trait object. Need to find actual drop fn. self.unpack_dyn_trait(&place, data)? } diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index e3afeda5b7c97..0075740e03178 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -386,7 +386,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ); self.write_immediate(val, dest) } - (ty::Dynamic(data_a, _, ty::Dyn), ty::Dynamic(data_b, _, ty::Dyn)) => { + (ty::Dynamic(data_a, _), ty::Dynamic(data_b, _)) => { let val = self.read_immediate(src)?; // MIR building generates odd NOP casts, prevent them from causing unexpected trouble. // See . @@ -436,7 +436,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let new_vptr = self.get_vtable_ptr(ty, data_b)?; self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest) } - (_, &ty::Dynamic(data, _, ty::Dyn)) => { + (_, &ty::Dynamic(data, _)) => { // Initial cast from sized to dyn trait let vtable = self.get_vtable_ptr(src_pointee_ty, data)?; let ptr = self.read_pointer(src)?; diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 91ed71ac3e54c..0e4a98f0941ac 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -469,7 +469,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { } interp_ok(Some((full_size, full_align))) } - ty::Dynamic(expected_trait, _, ty::Dyn) => { + ty::Dynamic(expected_trait, _) => { let vtable = metadata.unwrap_meta().to_pointer(self)?; // Read size and align from vtable (already checks size). interp_ok(Some(self.get_vtable_size_and_align(vtable, Some(expected_trait))?)) diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 5e3d0a15d8bc1..418dd658121db 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -181,7 +181,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { | ty::Ref(_, _, _) | ty::FnDef(_, _) | ty::FnPtr(..) - | ty::Dynamic(_, _, _) + | ty::Dynamic(_, _) | ty::Closure(_, _) | ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs index 7cabfd961212f..1c1c59da9d886 100644 --- a/compiler/rustc_const_eval/src/interpret/stack.rs +++ b/compiler/rustc_const_eval/src/interpret/stack.rs @@ -509,7 +509,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { | ty::Never | ty::Error(_) => true, - ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => false, + ty::Str | ty::Slice(_) | ty::Dynamic(_, _) | ty::Foreign(..) => false, ty::Tuple(tys) => tys.last().is_none_or(|ty| is_very_trivially_sized(*ty)), diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs index 870f9a396ae2b..d982ed9616742 100644 --- a/compiler/rustc_const_eval/src/interpret/traits.rs +++ b/compiler/rustc_const_eval/src/interpret/traits.rs @@ -109,7 +109,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { expected_trait: &'tcx ty::List>, ) -> InterpResult<'tcx, MPlaceTy<'tcx, M::Provenance>> { assert!( - matches!(mplace.layout.ty.kind(), ty::Dynamic(_, _, ty::Dyn)), + matches!(mplace.layout.ty.kind(), ty::Dynamic(_, _)), "`unpack_dyn_trait` only makes sense on `dyn*` types" ); let vtable = mplace.meta().unwrap_meta().to_pointer(self)?; diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 02e3d90f4af70..9adc3fa463180 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -449,7 +449,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> { ) -> InterpResult<'tcx> { let tail = self.ecx.tcx.struct_tail_for_codegen(pointee.ty, self.ecx.typing_env); match tail.kind() { - ty::Dynamic(data, _, ty::Dyn) => { + ty::Dynamic(data, _) => { let vtable = meta.unwrap_meta().to_pointer(self.ecx)?; // Make sure it is a genuine vtable pointer for the right trait. try_validation!( diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index 82c50fac6c0ee..b5de10c7dcd11 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -90,7 +90,7 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized { // Special treatment for special types, where the (static) layout is not sufficient. match *ty.kind() { // If it is a trait object, switch to the real type that was used to create it. - ty::Dynamic(data, _, ty::Dyn) => { + ty::Dynamic(data, _) => { // Dyn types. This is unsized, and the actual dynamic type of the data is given by the // vtable stored in the place metadata. // unsized values are never immediate, so we can assert_mem_place diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index 5bcf96abd8cb5..db651811551f3 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -41,7 +41,7 @@ impl<'tcx> Printer<'tcx> for TypeNamePrinter<'tcx> { | ty::FnPtr(..) | ty::Never | ty::Tuple(_) - | ty::Dynamic(_, _, _) + | ty::Dynamic(_, _) | ty::UnsafeBinder(_) => self.pretty_print_type(ty), // Placeholders (all printed as `_` to uniformize them). diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs index c3f965d845693..44cc2dec1cb52 100644 --- a/compiler/rustc_hir_analysis/src/collect/dump.rs +++ b/compiler/rustc_hir_analysis/src/collect/dump.rs @@ -152,7 +152,7 @@ pub(crate) fn vtables<'tcx>(tcx: TyCtxt<'tcx>) { ); continue; }; - let ty::Dynamic(data, _, _) = *ty.kind() else { + let ty::Dynamic(data, _) = *ty.kind() else { tcx.dcx() .span_err(attr.span(), "`rustc_dump_vtable` to type alias of dyn type"); continue; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs similarity index 51% rename from compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs rename to compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index 76bb59e3f0901..c248cd7fec2e5 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -1,16 +1,22 @@ +use rustc_ast::TraitObjectSyntax; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; -use rustc_errors::struct_span_code_err; +use rustc_errors::{ + Applicability, Diag, EmissionGuarantee, StashKey, Suggestions, struct_span_code_err, +}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS; +use rustc_hir::def_id::DefId; +use rustc_lint_defs::builtin::{BARE_TRAIT_OBJECTS, UNUSED_ASSOCIATED_TYPE_BOUNDS}; use rustc_middle::ty::elaborate::ClauseWithSupertraitSpan; use rustc_middle::ty::{ - self, BottomUpFolder, DynKind, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable, + self, BottomUpFolder, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, Upcast, }; +use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility; +use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName; use rustc_trait_selection::traits; use smallvec::{SmallVec, smallvec}; use tracing::{debug, instrument}; @@ -28,11 +34,24 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir_id: hir::HirId, hir_bounds: &[hir::PolyTraitRef<'tcx>], lifetime: &hir::Lifetime, - representation: DynKind, + syntax: TraitObjectSyntax, ) -> Ty<'tcx> { let tcx = self.tcx(); let dummy_self = tcx.types.trait_object_dummy_self; + match syntax { + TraitObjectSyntax::Dyn => {} + TraitObjectSyntax::None => { + match self.prohibit_or_lint_bare_trait_object_ty(span, hir_id, hir_bounds) { + // Don't continue with type analysis if the `dyn` keyword is missing. + // It generates confusing errors, especially if the user meant to use + // another keyword like `impl`. + Some(guar) => return Ty::new_error(tcx, guar), + None => {} + } + } + } + let mut user_written_bounds = Vec::new(); let mut potential_assoc_types = Vec::new(); for poly_trait_ref in hir_bounds.iter() { @@ -47,10 +66,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - let ast_bounds: Vec<_> = - hir_bounds.iter().map(|&trait_ref| hir::GenericBound::Trait(trait_ref)).collect(); - - self.add_default_traits(&mut user_written_bounds, dummy_self, &ast_bounds, None, span); + self.add_default_traits( + &mut user_written_bounds, + dummy_self, + &hir_bounds + .iter() + .map(|&trait_ref| hir::GenericBound::Trait(trait_ref)) + .collect::>(), + None, + span, + ); let (elaborated_trait_bounds, elaborated_projection_bounds) = traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied()); @@ -431,7 +456,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }; debug!(?region_bound); - Ty::new_dynamic(tcx, existential_predicates, region_bound, representation) + Ty::new_dynamic(tcx, existential_predicates, region_bound) } /// Check that elaborating the principal of a trait ref doesn't lead to projections @@ -483,6 +508,521 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }, ); } + + /// Prohibit or lint against *bare* trait object types depending on the edition. + /// + /// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`. + /// In edition 2021 and onward we emit a hard error for them. + fn prohibit_or_lint_bare_trait_object_ty( + &self, + span: Span, + hir_id: hir::HirId, + hir_bounds: &[hir::PolyTraitRef<'tcx>], + ) -> Option { + let tcx = self.tcx(); + let [poly_trait_ref, ..] = hir_bounds else { return None }; + + let in_path = match tcx.parent_hir_node(hir_id) { + hir::Node::Ty(hir::Ty { + kind: hir::TyKind::Path(hir::QPath::TypeRelative(qself, _)), + .. + }) + | hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Path(hir::QPath::TypeRelative(qself, _)), + .. + }) + | hir::Node::PatExpr(hir::PatExpr { + kind: hir::PatExprKind::Path(hir::QPath::TypeRelative(qself, _)), + .. + }) if qself.hir_id == hir_id => true, + _ => false, + }; + let needs_bracket = in_path + && !tcx + .sess + .source_map() + .span_to_prev_source(span) + .ok() + .is_some_and(|s| s.trim_end().ends_with('<')); + + let is_global = poly_trait_ref.trait_ref.path.is_global(); + + let mut sugg = vec![( + span.shrink_to_lo(), + format!( + "{}dyn {}", + if needs_bracket { "<" } else { "" }, + if is_global { "(" } else { "" }, + ), + )]; + + if is_global || needs_bracket { + sugg.push(( + span.shrink_to_hi(), + format!( + "{}{}", + if is_global { ")" } else { "" }, + if needs_bracket { ">" } else { "" }, + ), + )); + } + + if span.edition().at_least_rust_2021() { + let mut diag = rustc_errors::struct_span_code_err!( + self.dcx(), + span, + E0782, + "{}", + "expected a type, found a trait" + ); + if span.can_be_used_for_suggestions() + && poly_trait_ref.trait_ref.trait_def_id().is_some() + && !self.maybe_suggest_impl_trait(span, hir_id, hir_bounds, &mut diag) + && !self.maybe_suggest_dyn_trait(hir_id, sugg, &mut diag) + { + self.maybe_suggest_add_generic_impl_trait(span, hir_id, &mut diag); + } + // Check if the impl trait that we are considering is an impl of a local trait. + self.maybe_suggest_blanket_trait_impl(span, hir_id, &mut diag); + self.maybe_suggest_assoc_ty_bound(hir_id, &mut diag); + self.maybe_suggest_typoed_method( + hir_id, + poly_trait_ref.trait_ref.trait_def_id(), + &mut diag, + ); + // In case there is an associated type with the same name + // Add the suggestion to this error + if let Some(mut sugg) = + self.dcx().steal_non_err(span, StashKey::AssociatedTypeSuggestion) + && let Suggestions::Enabled(ref mut s1) = diag.suggestions + && let Suggestions::Enabled(ref mut s2) = sugg.suggestions + { + s1.append(s2); + sugg.cancel(); + } + Some(diag.emit()) + } else { + tcx.node_span_lint(BARE_TRAIT_OBJECTS, hir_id, span, |lint| { + lint.primary_message("trait objects without an explicit `dyn` are deprecated"); + if span.can_be_used_for_suggestions() { + lint.multipart_suggestion_verbose( + "if this is a dyn-compatible trait, use `dyn`", + sugg, + Applicability::MachineApplicable, + ); + } + self.maybe_suggest_blanket_trait_impl(span, hir_id, lint); + }); + None + } + } + + /// For a struct or enum with an invalid bare trait object field, suggest turning + /// it into a generic type bound. + fn maybe_suggest_add_generic_impl_trait( + &self, + span: Span, + hir_id: hir::HirId, + diag: &mut Diag<'_>, + ) -> bool { + let tcx = self.tcx(); + + let parent_hir_id = tcx.parent_hir_id(hir_id); + let parent_item = tcx.hir_get_parent_item(hir_id).def_id; + + let generics = match tcx.hir_node_by_def_id(parent_item) { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Struct(_, generics, variant), + .. + }) => { + if !variant.fields().iter().any(|field| field.hir_id == parent_hir_id) { + return false; + } + generics + } + hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics, def), .. }) => { + if !def + .variants + .iter() + .flat_map(|variant| variant.data.fields().iter()) + .any(|field| field.hir_id == parent_hir_id) + { + return false; + } + generics + } + _ => return false, + }; + + let Ok(rendered_ty) = tcx.sess.source_map().span_to_snippet(span) else { + return false; + }; + + let param = "TUV" + .chars() + .map(|c| c.to_string()) + .chain((0..).map(|i| format!("P{i}"))) + .find(|s| !generics.params.iter().any(|param| param.name.ident().as_str() == s)) + .expect("we definitely can find at least one param name to generate"); + let mut sugg = vec![(span, param.to_string())]; + if let Some(insertion_span) = generics.span_for_param_suggestion() { + sugg.push((insertion_span, format!(", {param}: {}", rendered_ty))); + } else { + sugg.push((generics.where_clause_span, format!("<{param}: {}>", rendered_ty))); + } + diag.multipart_suggestion_verbose( + "you might be missing a type parameter", + sugg, + Applicability::MachineApplicable, + ); + true + } + + /// Make sure that we are in the condition to suggest the blanket implementation. + fn maybe_suggest_blanket_trait_impl( + &self, + span: Span, + hir_id: hir::HirId, + diag: &mut Diag<'_, G>, + ) { + let tcx = self.tcx(); + let parent_id = tcx.hir_get_parent_item(hir_id).def_id; + if let hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(hir::Impl { self_ty: impl_self_ty, of_trait, generics, .. }), + .. + }) = tcx.hir_node_by_def_id(parent_id) + && hir_id == impl_self_ty.hir_id + { + let Some(of_trait) = of_trait else { + diag.span_suggestion_verbose( + impl_self_ty.span.shrink_to_hi(), + "you might have intended to implement this trait for a given type", + format!(" for /* Type */"), + Applicability::HasPlaceholders, + ); + return; + }; + if !of_trait.trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) { + return; + } + let of_trait_span = of_trait.trait_ref.path.span; + // make sure that we are not calling unwrap to abort during the compilation + let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else { + return; + }; + + let Ok(impl_trait_name) = self.tcx().sess.source_map().span_to_snippet(span) else { + return; + }; + let sugg = self.add_generic_param_suggestion(generics, span, &impl_trait_name); + diag.multipart_suggestion( + format!( + "alternatively use a blanket implementation to implement `{of_trait_name}` for \ + all types that also implement `{impl_trait_name}`" + ), + sugg, + Applicability::MaybeIncorrect, + ); + } + } + + /// Try our best to approximate when adding `dyn` would be helpful for a bare + /// trait object. + /// + /// Right now, this is if the type is either directly nested in another ty, + /// or if it's in the tail field within a struct. This approximates what the + /// user would've gotten on edition 2015, except for the case where we have + /// an *obvious* knock-on `Sized` error. + fn maybe_suggest_dyn_trait( + &self, + hir_id: hir::HirId, + sugg: Vec<(Span, String)>, + diag: &mut Diag<'_>, + ) -> bool { + let tcx = self.tcx(); + + // Look at the direct HIR parent, since we care about the relationship between + // the type and the thing that directly encloses it. + match tcx.parent_hir_node(hir_id) { + // These are all generally ok. Namely, when a trait object is nested + // into another expression or ty, it's either very certain that they + // missed the ty (e.g. `&Trait`) or it's not really possible to tell + // what their intention is, so let's not give confusing suggestions and + // just mention `dyn`. The user can make up their mind what to do here. + hir::Node::Ty(_) + | hir::Node::Expr(_) + | hir::Node::PatExpr(_) + | hir::Node::PathSegment(_) + | hir::Node::AssocItemConstraint(_) + | hir::Node::TraitRef(_) + | hir::Node::Item(_) + | hir::Node::WherePredicate(_) => {} + + hir::Node::Field(field) => { + // Enums can't have unsized fields, fields can only have an unsized tail field. + if let hir::Node::Item(hir::Item { + kind: hir::ItemKind::Struct(_, _, variant), .. + }) = tcx.parent_hir_node(field.hir_id) + && variant + .fields() + .last() + .is_some_and(|tail_field| tail_field.hir_id == field.hir_id) + { + // Ok + } else { + return false; + } + } + _ => return false, + } + + // FIXME: Only emit this suggestion if the trait is dyn-compatible. + diag.multipart_suggestion_verbose( + "you can add the `dyn` keyword if you want a trait object", + sugg, + Applicability::MachineApplicable, + ); + true + } + + fn add_generic_param_suggestion( + &self, + generics: &hir::Generics<'_>, + self_ty_span: Span, + impl_trait_name: &str, + ) -> Vec<(Span, String)> { + // check if the trait has generics, to make a correct suggestion + let param_name = generics.params.next_type_param_name(None); + + let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() { + (span, format!(", {param_name}: {impl_trait_name}")) + } else { + (generics.span, format!("<{param_name}: {impl_trait_name}>")) + }; + vec![(self_ty_span, param_name), add_generic_sugg] + } + + /// Make sure that we are in the condition to suggest `impl Trait`. + fn maybe_suggest_impl_trait( + &self, + span: Span, + hir_id: hir::HirId, + hir_bounds: &[hir::PolyTraitRef<'tcx>], + diag: &mut Diag<'_>, + ) -> bool { + let tcx = self.tcx(); + let parent_id = tcx.hir_get_parent_item(hir_id).def_id; + // FIXME: If `type_alias_impl_trait` is enabled, also look for `Trait0` + // and suggest `Trait0`. + // Functions are found in three different contexts. + // 1. Independent functions + // 2. Functions inside trait blocks + // 3. Functions inside impl blocks + let (sig, generics) = match tcx.hir_node_by_def_id(parent_id) { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn { sig, generics, .. }, .. + }) => (sig, generics), + hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Fn(sig, _), + generics, + .. + }) => (sig, generics), + hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Fn(sig, _), + generics, + .. + }) => (sig, generics), + _ => return false, + }; + let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(span) else { + return false; + }; + let impl_sugg = vec![(span.shrink_to_lo(), "impl ".to_string())]; + // Check if trait object is safe for suggesting dynamic dispatch. + let is_dyn_compatible = hir_bounds.iter().all(|bound| match bound.trait_ref.path.res { + Res::Def(DefKind::Trait, id) => tcx.is_dyn_compatible(id), + _ => false, + }); + + let borrowed = matches!( + tcx.parent_hir_node(hir_id), + hir::Node::Ty(hir::Ty { kind: hir::TyKind::Ref(..), .. }) + ); + + // Suggestions for function return type. + if let hir::FnRetTy::Return(ty) = sig.decl.output + && ty.peel_refs().hir_id == hir_id + { + let pre = if !is_dyn_compatible { + format!("`{trait_name}` is dyn-incompatible, ") + } else { + String::new() + }; + let msg = format!( + "{pre}use `impl {trait_name}` to return an opaque type, as long as you return a \ + single underlying type", + ); + + diag.multipart_suggestion_verbose(msg, impl_sugg, Applicability::MachineApplicable); + + // Suggest `Box` for return type + if is_dyn_compatible { + // If the return type is `&Trait`, we don't want + // the ampersand to be displayed in the `Box` + // suggestion. + let suggestion = if borrowed { + vec![(ty.span, format!("Box"))] + } else { + vec![ + (ty.span.shrink_to_lo(), "Box".to_string()), + ] + }; + + diag.multipart_suggestion_verbose( + "alternatively, you can return an owned trait object", + suggestion, + Applicability::MachineApplicable, + ); + } + return true; + } + + // Suggestions for function parameters. + for ty in sig.decl.inputs { + if ty.peel_refs().hir_id != hir_id { + continue; + } + let sugg = self.add_generic_param_suggestion(generics, span, &trait_name); + diag.multipart_suggestion_verbose( + format!("use a new generic type parameter, constrained by `{trait_name}`"), + sugg, + Applicability::MachineApplicable, + ); + diag.multipart_suggestion_verbose( + "you can also use an opaque type, but users won't be able to specify the type \ + parameter when calling the `fn`, having to rely exclusively on type inference", + impl_sugg, + Applicability::MachineApplicable, + ); + if !is_dyn_compatible { + diag.note(format!( + "`{trait_name}` is dyn-incompatible, otherwise a trait object could be used" + )); + } else { + // No ampersand in suggestion if it's borrowed already + let (dyn_str, paren_dyn_str) = + if borrowed { ("dyn ", "(dyn ") } else { ("&dyn ", "&(dyn ") }; + + let sugg = if let [_, _, ..] = hir_bounds { + // There is more than one trait bound, we need surrounding parentheses. + vec![ + (span.shrink_to_lo(), paren_dyn_str.to_string()), + (span.shrink_to_hi(), ")".to_string()), + ] + } else { + vec![(span.shrink_to_lo(), dyn_str.to_string())] + }; + diag.multipart_suggestion_verbose( + format!( + "alternatively, use a trait object to accept any type that implements \ + `{trait_name}`, accessing its methods at runtime using dynamic dispatch", + ), + sugg, + Applicability::MachineApplicable, + ); + } + return true; + } + false + } + + fn maybe_suggest_assoc_ty_bound(&self, hir_id: hir::HirId, diag: &mut Diag<'_>) { + let mut parents = self.tcx().hir_parent_iter(hir_id); + + if let Some((c_hir_id, hir::Node::AssocItemConstraint(constraint))) = parents.next() + && let Some(obj_ty) = constraint.ty() + && let Some((_, hir::Node::TraitRef(trait_ref))) = parents.next() + { + if let Some((_, hir::Node::Ty(ty))) = parents.next() + && let hir::TyKind::TraitObject(..) = ty.kind + { + // Assoc ty bounds aren't permitted inside trait object types. + return; + } + + if trait_ref + .path + .segments + .iter() + .find_map(|seg| { + seg.args.filter(|args| args.constraints.iter().any(|c| c.hir_id == c_hir_id)) + }) + .is_none_or(|args| args.parenthesized != hir::GenericArgsParentheses::No) + { + // Only consider angle-bracketed args (where we have a `=` to replace with `:`). + return; + } + + let lo = if constraint.gen_args.span_ext.is_dummy() { + constraint.ident.span + } else { + constraint.gen_args.span_ext + }; + let hi = obj_ty.span; + + if !lo.eq_ctxt(hi) { + return; + } + + diag.span_suggestion_verbose( + lo.between(hi), + "you might have meant to write a bound here", + ": ", + Applicability::MaybeIncorrect, + ); + } + } + + fn maybe_suggest_typoed_method( + &self, + hir_id: hir::HirId, + trait_def_id: Option, + diag: &mut Diag<'_>, + ) { + let tcx = self.tcx(); + let Some(trait_def_id) = trait_def_id else { + return; + }; + let hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Path(hir::QPath::TypeRelative(path_ty, segment)), + .. + }) = tcx.parent_hir_node(hir_id) + else { + return; + }; + if path_ty.hir_id != hir_id { + return; + } + let names: Vec<_> = tcx + .associated_items(trait_def_id) + .in_definition_order() + .filter(|assoc| assoc.namespace() == hir::def::Namespace::ValueNS) + .map(|cand| cand.name()) + .collect(); + if let Some(typo) = find_best_match_for_name(&names, segment.ident.name, None) { + diag.span_suggestion_verbose( + segment.ident.span, + format!( + "you may have misspelled this associated item, causing `{}` \ + to be interpreted as a type rather than a trait", + tcx.item_name(trait_def_id), + ), + typo, + Applicability::MaybeIncorrect, + ); + } + } } fn replace_dummy_self_with_error<'tcx, T: TypeFoldable>>( diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 0cf9cb7193f72..165051744641f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -859,7 +859,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg) } // Point at the trait object that couldn't satisfy the bound. - ty::Dynamic(preds, _, _) => { + ty::Dynamic(preds, _) => { for pred in preds.iter() { match pred.skip_binder() { ty::ExistentialPredicate::Trait(tr) => { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs deleted file mode 100644 index 56998b5b53cc4..0000000000000 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ /dev/null @@ -1,533 +0,0 @@ -use rustc_ast::TraitObjectSyntax; -use rustc_errors::codes::*; -use rustc_errors::{Diag, EmissionGuarantee, ErrorGuaranteed, StashKey, Suggestions}; -use rustc_hir as hir; -use rustc_hir::def::{DefKind, Namespace, Res}; -use rustc_hir::def_id::DefId; -use rustc_lint_defs::Applicability; -use rustc_lint_defs::builtin::BARE_TRAIT_OBJECTS; -use rustc_span::Span; -use rustc_span::edit_distance::find_best_match_for_name; -use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName; - -use super::HirTyLowerer; - -impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { - /// Prohibit or lint against *bare* trait object types depending on the edition. - /// - /// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`. - /// In edition 2021 and onward we emit a hard error for them. - pub(super) fn prohibit_or_lint_bare_trait_object_ty( - &self, - self_ty: &hir::Ty<'_>, - ) -> Option { - let tcx = self.tcx(); - - let poly_trait_ref = if let hir::TyKind::TraitObject([poly_trait_ref, ..], tagged_ptr) = - self_ty.kind - && let TraitObjectSyntax::None = tagged_ptr.tag() - { - poly_trait_ref - } else { - return None; - }; - - let in_path = match tcx.parent_hir_node(self_ty.hir_id) { - hir::Node::Ty(hir::Ty { - kind: hir::TyKind::Path(hir::QPath::TypeRelative(qself, _)), - .. - }) - | hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Path(hir::QPath::TypeRelative(qself, _)), - .. - }) - | hir::Node::PatExpr(hir::PatExpr { - kind: hir::PatExprKind::Path(hir::QPath::TypeRelative(qself, _)), - .. - }) if qself.hir_id == self_ty.hir_id => true, - _ => false, - }; - let needs_bracket = in_path - && !tcx - .sess - .source_map() - .span_to_prev_source(self_ty.span) - .ok() - .is_some_and(|s| s.trim_end().ends_with('<')); - - let is_global = poly_trait_ref.trait_ref.path.is_global(); - - let mut sugg = vec![( - self_ty.span.shrink_to_lo(), - format!( - "{}dyn {}", - if needs_bracket { "<" } else { "" }, - if is_global { "(" } else { "" }, - ), - )]; - - if is_global || needs_bracket { - sugg.push(( - self_ty.span.shrink_to_hi(), - format!( - "{}{}", - if is_global { ")" } else { "" }, - if needs_bracket { ">" } else { "" }, - ), - )); - } - - if self_ty.span.edition().at_least_rust_2021() { - let mut diag = rustc_errors::struct_span_code_err!( - self.dcx(), - self_ty.span, - E0782, - "{}", - "expected a type, found a trait" - ); - if self_ty.span.can_be_used_for_suggestions() - && poly_trait_ref.trait_ref.trait_def_id().is_some() - && !self.maybe_suggest_impl_trait(self_ty, &mut diag) - && !self.maybe_suggest_dyn_trait(self_ty, sugg, &mut diag) - { - self.maybe_suggest_add_generic_impl_trait(self_ty, &mut diag); - } - // Check if the impl trait that we are considering is an impl of a local trait. - self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag); - self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag); - self.maybe_suggest_typoed_method( - self_ty, - poly_trait_ref.trait_ref.trait_def_id(), - &mut diag, - ); - // In case there is an associated type with the same name - // Add the suggestion to this error - if let Some(mut sugg) = - self.dcx().steal_non_err(self_ty.span, StashKey::AssociatedTypeSuggestion) - && let Suggestions::Enabled(ref mut s1) = diag.suggestions - && let Suggestions::Enabled(ref mut s2) = sugg.suggestions - { - s1.append(s2); - sugg.cancel(); - } - Some(diag.emit()) - } else { - tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| { - lint.primary_message("trait objects without an explicit `dyn` are deprecated"); - if self_ty.span.can_be_used_for_suggestions() { - lint.multipart_suggestion_verbose( - "if this is a dyn-compatible trait, use `dyn`", - sugg, - Applicability::MachineApplicable, - ); - } - self.maybe_suggest_blanket_trait_impl(self_ty, lint); - }); - None - } - } - - /// For a struct or enum with an invalid bare trait object field, suggest turning - /// it into a generic type bound. - fn maybe_suggest_add_generic_impl_trait( - &self, - self_ty: &hir::Ty<'_>, - diag: &mut Diag<'_>, - ) -> bool { - let tcx = self.tcx(); - - let parent_hir_id = tcx.parent_hir_id(self_ty.hir_id); - let parent_item = tcx.hir_get_parent_item(self_ty.hir_id).def_id; - - let generics = match tcx.hir_node_by_def_id(parent_item) { - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Struct(_, generics, variant), - .. - }) => { - if !variant.fields().iter().any(|field| field.hir_id == parent_hir_id) { - return false; - } - generics - } - hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics, def), .. }) => { - if !def - .variants - .iter() - .flat_map(|variant| variant.data.fields().iter()) - .any(|field| field.hir_id == parent_hir_id) - { - return false; - } - generics - } - _ => return false, - }; - - let Ok(rendered_ty) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { - return false; - }; - - let param = "TUV" - .chars() - .map(|c| c.to_string()) - .chain((0..).map(|i| format!("P{i}"))) - .find(|s| !generics.params.iter().any(|param| param.name.ident().as_str() == s)) - .expect("we definitely can find at least one param name to generate"); - let mut sugg = vec![(self_ty.span, param.to_string())]; - if let Some(insertion_span) = generics.span_for_param_suggestion() { - sugg.push((insertion_span, format!(", {param}: {}", rendered_ty))); - } else { - sugg.push((generics.where_clause_span, format!("<{param}: {}>", rendered_ty))); - } - diag.multipart_suggestion_verbose( - "you might be missing a type parameter", - sugg, - Applicability::MachineApplicable, - ); - true - } - /// Make sure that we are in the condition to suggest the blanket implementation. - fn maybe_suggest_blanket_trait_impl( - &self, - self_ty: &hir::Ty<'_>, - diag: &mut Diag<'_, G>, - ) { - let tcx = self.tcx(); - let parent_id = tcx.hir_get_parent_item(self_ty.hir_id).def_id; - if let hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { self_ty: impl_self_ty, of_trait, generics, .. }), - .. - }) = tcx.hir_node_by_def_id(parent_id) - && self_ty.hir_id == impl_self_ty.hir_id - { - let Some(of_trait) = of_trait else { - diag.span_suggestion_verbose( - impl_self_ty.span.shrink_to_hi(), - "you might have intended to implement this trait for a given type", - format!(" for /* Type */"), - Applicability::HasPlaceholders, - ); - return; - }; - if !of_trait.trait_ref.trait_def_id().is_some_and(|def_id| def_id.is_local()) { - return; - } - let of_trait_span = of_trait.trait_ref.path.span; - // make sure that we are not calling unwrap to abort during the compilation - let Ok(of_trait_name) = tcx.sess.source_map().span_to_snippet(of_trait_span) else { - return; - }; - - let Ok(impl_trait_name) = self.tcx().sess.source_map().span_to_snippet(self_ty.span) - else { - return; - }; - let sugg = self.add_generic_param_suggestion(generics, self_ty.span, &impl_trait_name); - diag.multipart_suggestion( - format!( - "alternatively use a blanket implementation to implement `{of_trait_name}` for \ - all types that also implement `{impl_trait_name}`" - ), - sugg, - Applicability::MaybeIncorrect, - ); - } - } - - /// Try our best to approximate when adding `dyn` would be helpful for a bare - /// trait object. - /// - /// Right now, this is if the type is either directly nested in another ty, - /// or if it's in the tail field within a struct. This approximates what the - /// user would've gotten on edition 2015, except for the case where we have - /// an *obvious* knock-on `Sized` error. - fn maybe_suggest_dyn_trait( - &self, - self_ty: &hir::Ty<'_>, - sugg: Vec<(Span, String)>, - diag: &mut Diag<'_>, - ) -> bool { - let tcx = self.tcx(); - - // Look at the direct HIR parent, since we care about the relationship between - // the type and the thing that directly encloses it. - match tcx.parent_hir_node(self_ty.hir_id) { - // These are all generally ok. Namely, when a trait object is nested - // into another expression or ty, it's either very certain that they - // missed the ty (e.g. `&Trait`) or it's not really possible to tell - // what their intention is, so let's not give confusing suggestions and - // just mention `dyn`. The user can make up their mind what to do here. - hir::Node::Ty(_) - | hir::Node::Expr(_) - | hir::Node::PatExpr(_) - | hir::Node::PathSegment(_) - | hir::Node::AssocItemConstraint(_) - | hir::Node::TraitRef(_) - | hir::Node::Item(_) - | hir::Node::WherePredicate(_) => {} - - hir::Node::Field(field) => { - // Enums can't have unsized fields, fields can only have an unsized tail field. - if let hir::Node::Item(hir::Item { - kind: hir::ItemKind::Struct(_, _, variant), .. - }) = tcx.parent_hir_node(field.hir_id) - && variant - .fields() - .last() - .is_some_and(|tail_field| tail_field.hir_id == field.hir_id) - { - // Ok - } else { - return false; - } - } - _ => return false, - } - - // FIXME: Only emit this suggestion if the trait is dyn-compatible. - diag.multipart_suggestion_verbose( - "you can add the `dyn` keyword if you want a trait object", - sugg, - Applicability::MachineApplicable, - ); - true - } - - fn add_generic_param_suggestion( - &self, - generics: &hir::Generics<'_>, - self_ty_span: Span, - impl_trait_name: &str, - ) -> Vec<(Span, String)> { - // check if the trait has generics, to make a correct suggestion - let param_name = generics.params.next_type_param_name(None); - - let add_generic_sugg = if let Some(span) = generics.span_for_param_suggestion() { - (span, format!(", {param_name}: {impl_trait_name}")) - } else { - (generics.span, format!("<{param_name}: {impl_trait_name}>")) - }; - vec![(self_ty_span, param_name), add_generic_sugg] - } - - /// Make sure that we are in the condition to suggest `impl Trait`. - fn maybe_suggest_impl_trait(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) -> bool { - let tcx = self.tcx(); - let parent_id = tcx.hir_get_parent_item(self_ty.hir_id).def_id; - // FIXME: If `type_alias_impl_trait` is enabled, also look for `Trait0` - // and suggest `Trait0`. - // Functions are found in three different contexts. - // 1. Independent functions - // 2. Functions inside trait blocks - // 3. Functions inside impl blocks - let (sig, generics) = match tcx.hir_node_by_def_id(parent_id) { - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Fn { sig, generics, .. }, .. - }) => (sig, generics), - hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(sig, _), - generics, - .. - }) => (sig, generics), - hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Fn(sig, _), - generics, - .. - }) => (sig, generics), - _ => return false, - }; - let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { - return false; - }; - let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())]; - // Check if trait object is safe for suggesting dynamic dispatch. - let is_dyn_compatible = match self_ty.kind { - hir::TyKind::TraitObject(objects, ..) => { - objects.iter().all(|o| match o.trait_ref.path.res { - Res::Def(DefKind::Trait, id) => tcx.is_dyn_compatible(id), - _ => false, - }) - } - _ => false, - }; - - let borrowed = matches!( - tcx.parent_hir_node(self_ty.hir_id), - hir::Node::Ty(hir::Ty { kind: hir::TyKind::Ref(..), .. }) - ); - - // Suggestions for function return type. - if let hir::FnRetTy::Return(ty) = sig.decl.output - && ty.peel_refs().hir_id == self_ty.hir_id - { - let pre = if !is_dyn_compatible { - format!("`{trait_name}` is dyn-incompatible, ") - } else { - String::new() - }; - let msg = format!( - "{pre}use `impl {trait_name}` to return an opaque type, as long as you return a \ - single underlying type", - ); - - diag.multipart_suggestion_verbose(msg, impl_sugg, Applicability::MachineApplicable); - - // Suggest `Box` for return type - if is_dyn_compatible { - // If the return type is `&Trait`, we don't want - // the ampersand to be displayed in the `Box` - // suggestion. - let suggestion = if borrowed { - vec![(ty.span, format!("Box"))] - } else { - vec![ - (ty.span.shrink_to_lo(), "Box".to_string()), - ] - }; - - diag.multipart_suggestion_verbose( - "alternatively, you can return an owned trait object", - suggestion, - Applicability::MachineApplicable, - ); - } - return true; - } - - // Suggestions for function parameters. - for ty in sig.decl.inputs { - if ty.peel_refs().hir_id != self_ty.hir_id { - continue; - } - let sugg = self.add_generic_param_suggestion(generics, self_ty.span, &trait_name); - diag.multipart_suggestion_verbose( - format!("use a new generic type parameter, constrained by `{trait_name}`"), - sugg, - Applicability::MachineApplicable, - ); - diag.multipart_suggestion_verbose( - "you can also use an opaque type, but users won't be able to specify the type \ - parameter when calling the `fn`, having to rely exclusively on type inference", - impl_sugg, - Applicability::MachineApplicable, - ); - if !is_dyn_compatible { - diag.note(format!( - "`{trait_name}` is dyn-incompatible, otherwise a trait object could be used" - )); - } else { - // No ampersand in suggestion if it's borrowed already - let (dyn_str, paren_dyn_str) = - if borrowed { ("dyn ", "(dyn ") } else { ("&dyn ", "&(dyn ") }; - - let sugg = if let hir::TyKind::TraitObject([_, _, ..], _) = self_ty.kind { - // There is more than one trait bound, we need surrounding parentheses. - vec![ - (self_ty.span.shrink_to_lo(), paren_dyn_str.to_string()), - (self_ty.span.shrink_to_hi(), ")".to_string()), - ] - } else { - vec![(self_ty.span.shrink_to_lo(), dyn_str.to_string())] - }; - diag.multipart_suggestion_verbose( - format!( - "alternatively, use a trait object to accept any type that implements \ - `{trait_name}`, accessing its methods at runtime using dynamic dispatch", - ), - sugg, - Applicability::MachineApplicable, - ); - } - return true; - } - false - } - - fn maybe_suggest_assoc_ty_bound(&self, self_ty: &hir::Ty<'_>, diag: &mut Diag<'_>) { - let mut parents = self.tcx().hir_parent_iter(self_ty.hir_id); - - if let Some((c_hir_id, hir::Node::AssocItemConstraint(constraint))) = parents.next() - && let Some(obj_ty) = constraint.ty() - && let Some((_, hir::Node::TraitRef(trait_ref))) = parents.next() - { - if let Some((_, hir::Node::Ty(ty))) = parents.next() - && let hir::TyKind::TraitObject(..) = ty.kind - { - // Assoc ty bounds aren't permitted inside trait object types. - return; - } - - if trait_ref - .path - .segments - .iter() - .find_map(|seg| { - seg.args.filter(|args| args.constraints.iter().any(|c| c.hir_id == c_hir_id)) - }) - .is_none_or(|args| args.parenthesized != hir::GenericArgsParentheses::No) - { - // Only consider angle-bracketed args (where we have a `=` to replace with `:`). - return; - } - - let lo = if constraint.gen_args.span_ext.is_dummy() { - constraint.ident.span - } else { - constraint.gen_args.span_ext - }; - let hi = obj_ty.span; - - if !lo.eq_ctxt(hi) { - return; - } - - diag.span_suggestion_verbose( - lo.between(hi), - "you might have meant to write a bound here", - ": ", - Applicability::MaybeIncorrect, - ); - } - } - - fn maybe_suggest_typoed_method( - &self, - self_ty: &hir::Ty<'_>, - trait_def_id: Option, - diag: &mut Diag<'_>, - ) { - let tcx = self.tcx(); - let Some(trait_def_id) = trait_def_id else { - return; - }; - let hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Path(hir::QPath::TypeRelative(path_ty, segment)), - .. - }) = tcx.parent_hir_node(self_ty.hir_id) - else { - return; - }; - if path_ty.hir_id != self_ty.hir_id { - return; - } - let names: Vec<_> = tcx - .associated_items(trait_def_id) - .in_definition_order() - .filter(|assoc| assoc.namespace() == Namespace::ValueNS) - .map(|cand| cand.name()) - .collect(); - if let Some(typo) = find_best_match_for_name(&names, segment.ident.name, None) { - diag.span_suggestion_verbose( - segment.ident.span, - format!( - "you may have misspelled this associated item, causing `{}` \ - to be interpreted as a type rather than a trait", - tcx.item_name(trait_def_id), - ), - typo, - Applicability::MaybeIncorrect, - ); - } - } -} 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 c5e079fe89ac4..9b198d044542f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -15,15 +15,13 @@ mod bounds; mod cmse; -mod dyn_compatibility; +mod dyn_trait; pub mod errors; pub mod generics; -mod lint; use std::assert_matches::assert_matches; use std::slice; -use rustc_ast::TraitObjectSyntax; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{ @@ -2428,19 +2426,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ), hir::TyKind::TraitObject(bounds, tagged_ptr) => { let lifetime = tagged_ptr.pointer(); - let repr = tagged_ptr.tag(); - - if let Some(guar) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty) { - // Don't continue with type analysis if the `dyn` keyword is missing - // It generates confusing errors, especially if the user meant to use another - // keyword like `impl` - Ty::new_error(tcx, guar) - } else { - let repr = match repr { - TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn, - }; - self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr) - } + let syntax = tagged_ptr.tag(); + self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, syntax) } // If we encounter a fully qualified path with RTN generics, then it must have // *not* gone through `lower_ty_maybe_return_type_notation`, and therefore diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index 960ec7f66ab15..be841675821c1 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -281,7 +281,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_args(current, data.def_id, data.args, variance); } - ty::Dynamic(data, r, _) => { + ty::Dynamic(data, r) => { // The type `dyn Trait +'a` is covariant w/r/t `'a`: self.add_constraints_from_region(current, r, variance); diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 27540fd1a4382..40b21c45bc564 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -103,7 +103,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(match *t.kind() { ty::Slice(_) | ty::Str => Some(PointerKind::Length), - ty::Dynamic(tty, _, ty::Dyn) => Some(PointerKind::VTable(tty)), + ty::Dynamic(tty, _) => Some(PointerKind::VTable(tty)), ty::Adt(def, args) if def.is_struct() => match def.non_enum_variant().tail_opt() { None => Some(PointerKind::Thin), Some(f) => { @@ -250,9 +250,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { // cases now. We do a more thorough check at the end, once // inference is more completely known. match cast_ty.kind() { - ty::Dynamic(_, _, ty::Dyn) | ty::Slice(..) => { - Err(check.report_cast_to_unsized_type(fcx)) - } + ty::Dynamic(_, _) | ty::Slice(..) => Err(check.report_cast_to_unsized_type(fcx)), _ => Ok(check), } } @@ -900,7 +898,6 @@ impl<'a, 'tcx> CastCheck<'tcx> { &src_tty.without_auto_traits().collect::>(), ), tcx.lifetimes.re_erased, - ty::Dyn, ); let dst_obj = Ty::new_dynamic( tcx, @@ -908,7 +905,6 @@ impl<'a, 'tcx> CastCheck<'tcx> { &dst_tty.without_auto_traits().collect::>(), ), tcx.lifetimes.re_erased, - ty::Dyn, ); // `dyn Src = dyn Dst`, this checks for matching traits/generics/projections diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index b99f811db1a14..ced2cf2b57b14 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -558,7 +558,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { | ty::Slice(_) | ty::FnDef(_, _) | ty::FnPtr(_, _) - | ty::Dynamic(_, _, _) + | ty::Dynamic(_, _) | ty::Closure(_, _) | ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index c8f6c06b720dc..a39ac0fcb6e3e 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1008,7 +1008,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg) } // Point at the trait object that couldn't satisfy the bound. - ty::Dynamic(preds, _, _) => { + ty::Dynamic(preds, _) => { for pred in preds.iter() { match pred.skip_binder() { ty::ExistentialPredicate::Trait(tr) => { diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs index e1c51ff829907..703f757abd50c 100644 --- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs +++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs @@ -66,11 +66,11 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait { && tcx.is_lang_item(did, LangItem::Deref) // the self type is `dyn t_principal` && let self_ty = tcx.type_of(item.owner_id).instantiate_identity() - && let ty::Dynamic(data, _, ty::Dyn) = self_ty.kind() + && let ty::Dynamic(data, _) = self_ty.kind() && let Some(self_principal) = data.principal() // `::Target` is `dyn target_principal` && let Some(target) = cx.get_associated_type(self_ty, did, sym::Target) - && let ty::Dynamic(data, _, ty::Dyn) = target.kind() + && let ty::Dynamic(data, _) = target.kind() && let Some(target_principal) = data.principal() // `target_principal` is a supertrait of `t_principal` && let Some(supertrait_principal) = supertraits(tcx, self_principal.with_self_ty(tcx, self_ty)) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 88527fa2e6e78..eaec0c9857d28 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -320,7 +320,7 @@ fn lint_wide_pointer<'tcx>( }; (!ty.is_sized(cx.tcx, cx.typing_env())) - .then(|| (refs, modifiers, matches!(ty.kind(), ty::Dynamic(_, _, ty::Dyn)))) + .then(|| (refs, modifiers, matches!(ty.kind(), ty::Dynamic(_, _)))) }; // the left and right operands can have references, remove any explicit references diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 22d89d2461273..95c5bea6be898 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -312,7 +312,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { }) .map(|inner| MustUsePath::Opaque(Box::new(inner))) } - ty::Dynamic(binders, _, _) => binders.iter().find_map(|predicate| { + ty::Dynamic(binders, _) => binders.iter().find_map(|predicate| { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { let def_id = trait_ref.def_id; diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 79700d485c440..7d3e2c9965dad 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -574,7 +574,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { | ty::Ref(_, _, _) | ty::FnDef(_, _) | ty::FnPtr(..) - | ty::Dynamic(_, _, _) + | ty::Dynamic(_, _) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(_, _) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 2114d080dfa43..9524057eebc6c 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -812,7 +812,7 @@ where | ty::CoroutineWitness(..) | ty::Foreign(..) | ty::Pat(_, _) - | ty::Dynamic(_, _, ty::Dyn) => { + | ty::Dynamic(_, _) => { bug!("TyAndLayout::field({:?}): not applicable", this) } @@ -878,7 +878,7 @@ where // `std::mem::uninitialized::<&dyn Trait>()`, for example. if let ty::Adt(def, args) = metadata.kind() && tcx.is_lang_item(def.did(), LangItem::DynMetadata) - && let ty::Dynamic(data, _, ty::Dyn) = args.type_at(0).kind() + && let ty::Dynamic(data, _) = args.type_at(0).kind() { mk_dyn_vtable(data.principal()) } else { @@ -887,7 +887,7 @@ where } else { match tcx.struct_tail_for_codegen(pointee, cx.typing_env()).kind() { ty::Slice(_) | ty::Str => tcx.types.usize, - ty::Dynamic(data, _, ty::Dyn) => mk_dyn_vtable(data.principal()), + ty::Dynamic(data, _) => mk_dyn_vtable(data.principal()), _ => bug!("TyAndLayout::field({:?}): not applicable", this), } }; diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index fc821ffdaa68b..1b7ef8de8454a 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -784,14 +784,12 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { }, }, ty::Adt(def, args) => self.print_def_path(def.did(), args)?, - ty::Dynamic(data, r, repr) => { + ty::Dynamic(data, r) => { let print_r = self.should_print_optional_region(r); if print_r { write!(self, "(")?; } - match repr { - ty::Dyn => write!(self, "dyn ")?, - } + write!(self, "dyn ")?; data.print(self)?; if print_r { write!(self, " + ")?; diff --git a/compiler/rustc_middle/src/ty/significant_drop_order.rs b/compiler/rustc_middle/src/ty/significant_drop_order.rs index 5ada9ecc80cf3..f1aa7076d98ac 100644 --- a/compiler/rustc_middle/src/ty/significant_drop_order.rs +++ b/compiler/rustc_middle/src/ty/significant_drop_order.rs @@ -132,7 +132,7 @@ pub fn ty_dtor_span<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option { | ty::Ref(_, _, _) | ty::FnPtr(_, _) | ty::Tuple(_) - | ty::Dynamic(_, _, _) + | ty::Dynamic(_, _) | ty::Alias(_, _) | ty::Bound(_, _) | ty::Pat(_, _) diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 89ef46b1ae571..11d109b463d90 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -390,11 +390,9 @@ impl<'tcx> TypeSuperFoldable> for Ty<'tcx> { ty::Array(typ, sz) => ty::Array(typ.try_fold_with(folder)?, sz.try_fold_with(folder)?), ty::Slice(typ) => ty::Slice(typ.try_fold_with(folder)?), ty::Adt(tid, args) => ty::Adt(tid, args.try_fold_with(folder)?), - ty::Dynamic(trait_ty, region, representation) => ty::Dynamic( - trait_ty.try_fold_with(folder)?, - region.try_fold_with(folder)?, - representation, - ), + ty::Dynamic(trait_ty, region) => { + ty::Dynamic(trait_ty.try_fold_with(folder)?, region.try_fold_with(folder)?) + } ty::Tuple(ts) => ty::Tuple(ts.try_fold_with(folder)?), ty::FnDef(def_id, args) => ty::FnDef(def_id, args.try_fold_with(folder)?), ty::FnPtr(sig_tys, hdr) => ty::FnPtr(sig_tys.try_fold_with(folder)?, hdr), @@ -437,8 +435,8 @@ impl<'tcx> TypeSuperFoldable> for Ty<'tcx> { ty::Array(typ, sz) => ty::Array(typ.fold_with(folder), sz.fold_with(folder)), ty::Slice(typ) => ty::Slice(typ.fold_with(folder)), ty::Adt(tid, args) => ty::Adt(tid, args.fold_with(folder)), - ty::Dynamic(trait_ty, region, representation) => { - ty::Dynamic(trait_ty.fold_with(folder), region.fold_with(folder), representation) + ty::Dynamic(trait_ty, region) => { + ty::Dynamic(trait_ty.fold_with(folder), region.fold_with(folder)) } ty::Tuple(ts) => ty::Tuple(ts.fold_with(folder)), ty::FnDef(def_id, args) => ty::FnDef(def_id, args.fold_with(folder)), @@ -481,7 +479,7 @@ impl<'tcx> TypeSuperVisitable> for Ty<'tcx> { } ty::Slice(typ) => typ.visit_with(visitor), ty::Adt(_, args) => args.visit_with(visitor), - ty::Dynamic(trait_ty, reg, _) => { + ty::Dynamic(trait_ty, reg) => { try_visit!(trait_ty.visit_with(visitor)); reg.visit_with(visitor) } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 755fc68d86f34..2bea797799958 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -17,7 +17,7 @@ use rustc_span::{DUMMY_SP, Span, Symbol, sym}; use rustc_type_ir::TyKind::*; use rustc_type_ir::solve::SizedTraitKind; use rustc_type_ir::walk::TypeWalker; -use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, DynKind, TypeVisitableExt, elaborate}; +use rustc_type_ir::{self as ir, BoundVar, CollectAndApply, TypeVisitableExt, elaborate}; use tracing::instrument; use ty::util::IntTypeExt; @@ -734,7 +734,6 @@ impl<'tcx> Ty<'tcx> { tcx: TyCtxt<'tcx>, obj: &'tcx List>, reg: ty::Region<'tcx>, - repr: DynKind, ) -> Ty<'tcx> { if cfg!(debug_assertions) { let projection_count = obj @@ -767,7 +766,7 @@ impl<'tcx> Ty<'tcx> { but it has {projection_count}" ); } - Ty::new(tcx, Dynamic(obj, reg, repr)) + Ty::new(tcx, Dynamic(obj, reg)) } #[inline] @@ -980,9 +979,8 @@ impl<'tcx> rustc_type_ir::inherent::Ty> for Ty<'tcx> { interner: TyCtxt<'tcx>, preds: &'tcx List>, region: ty::Region<'tcx>, - kind: ty::DynKind, ) -> Self { - Ty::new_dynamic(interner, preds, region, kind) + Ty::new_dynamic(interner, preds, region) } fn new_coroutine( @@ -1356,7 +1354,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn is_trait(self) -> bool { - matches!(self.kind(), Dynamic(_, _, ty::Dyn)) + matches!(self.kind(), Dynamic(_, _)) } #[inline] @@ -1671,7 +1669,7 @@ impl<'tcx> Ty<'tcx> { ty::Str | ty::Slice(_) => Ok(tcx.types.usize), - ty::Dynamic(_, _, ty::Dyn) => { + ty::Dynamic(_, _) => { let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, DUMMY_SP); Ok(tcx.type_of(dyn_metadata).instantiate(tcx, &[tail.into()])) } @@ -1853,7 +1851,7 @@ impl<'tcx> Ty<'tcx> { | ty::Never | ty::Error(_) => true, - ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) => match sizedness { + ty::Str | ty::Slice(_) | ty::Dynamic(_, _) => match sizedness { SizedTraitKind::Sized => false, SizedTraitKind::MetaSized => true, }, diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 48718cad597a8..18f41c8b97f64 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -152,7 +152,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { | ty::Slice(_) | ty::FnDef(_, _) | ty::FnPtr(..) - | ty::Dynamic(_, _, _) + | ty::Dynamic(_, _) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(_, _) @@ -196,7 +196,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> { | ty::Ref(_, _, _) | ty::FnDef(_, _) | ty::FnPtr(..) - | ty::Dynamic(_, _, _) + | ty::Dynamic(_, _) | ty::CoroutineWitness(..) | ty::Never | ty::UnsafeBinder(_) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 4603c695dedd5..d3cc23818c7e1 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1891,7 +1891,7 @@ fn check_must_not_suspend_ty<'tcx>( } has_emitted } - ty::Dynamic(binder, _, _) => { + ty::Dynamic(binder, _) => { let mut has_emitted = false; for predicate in binder.iter() { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index a8f2b4e8db662..4b4ec4956eb88 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -390,7 +390,7 @@ impl<'a, D: SolverDelegate, I: Interner> Canonicalizer<'a, D, I> { | ty::FnDef(_, _) | ty::FnPtr(..) | ty::UnsafeBinder(_) - | ty::Dynamic(_, _, _) + | ty::Dynamic(_, _) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(_, _) 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 fb777496e31eb..7de7870bbb12c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -86,7 +86,7 @@ where ) -> Result, NoSolution> { Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| { let cx = ecx.cx(); - let ty::Dynamic(bounds, _, _) = goal.predicate.self_ty().kind() else { + let ty::Dynamic(bounds, _) = goal.predicate.self_ty().kind() else { panic!("expected object type in `probe_and_consider_object_bound_candidate`"); }; match structural_traits::predicates_for_object_candidate( 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 f6eab286ba70b..c40739d12e680 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 @@ -383,7 +383,7 @@ pub(in crate::solve) fn extract_tupled_inputs_and_output_from_callable( | ty::Slice(_) | ty::RawPtr(_, _) | ty::Ref(_, _, _) - | ty::Dynamic(_, _, _) + | ty::Dynamic(_, _) | ty::Coroutine(_, _) | ty::CoroutineWitness(..) | ty::Never 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 54b92ebac1ded..653c59c5d4241 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 @@ -665,7 +665,7 @@ where ty::Str | ty::Slice(_) => Ty::new_usize(cx), - ty::Dynamic(_, _, ty::Dyn) => { + ty::Dynamic(_, _) => { let dyn_metadata = cx.require_lang_item(SolverLangItem::DynMetadata); cx.type_of(dyn_metadata) .instantiate(cx, &[I::GenericArg::from(goal.predicate.self_ty())]) @@ -916,7 +916,7 @@ where | ty::Adt(_, _) | ty::Str | ty::Slice(_) - | ty::Dynamic(_, _, _) + | ty::Dynamic(_, _) | ty::Tuple(_) | ty::Error(_) => self_ty.discriminant_ty(ecx.cx()), 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 a69e867289cee..3974114e9b43c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -817,15 +817,13 @@ where } // Trait upcasting, or `dyn Trait + Auto + 'a` -> `dyn Trait + 'b`. - ( - ty::Dynamic(a_data, a_region, ty::Dyn), - ty::Dynamic(b_data, b_region, ty::Dyn), - ) => ecx.consider_builtin_dyn_upcast_candidates( - goal, a_data, a_region, b_data, b_region, - ), + (ty::Dynamic(a_data, a_region), ty::Dynamic(b_data, b_region)) => ecx + .consider_builtin_dyn_upcast_candidates( + goal, a_data, a_region, b_data, b_region, + ), // `T` -> `dyn Trait` unsizing. - (_, ty::Dynamic(b_region, b_data, ty::Dyn)) => result_to_single( + (_, ty::Dynamic(b_region, b_data)) => result_to_single( ecx.consider_builtin_unsize_to_dyn_candidate(goal, b_region, b_data), ), diff --git a/compiler/rustc_passes/src/check_export.rs b/compiler/rustc_passes/src/check_export.rs index 6eded3a9eb9ac..fee920221e1d1 100644 --- a/compiler/rustc_passes/src/check_export.rs +++ b/compiler/rustc_passes/src/check_export.rs @@ -295,7 +295,7 @@ impl<'tcx, 'a> TypeVisitor> for ExportableItemsChecker<'tcx, 'a> { | ty::Ref(_, _, _) | ty::Param(_) | ty::Closure(_, _) - | ty::Dynamic(_, _, _) + | ty::Dynamic(_, _) | ty::Coroutine(_, _) | ty::Foreign(_) | ty::Str diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index c9bf4fe4449b0..d9f8085083ebd 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -407,7 +407,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { | ty::FnDef(_, _) | ty::FnPtr(..) | ty::Pat(_, _) - | ty::Dynamic(_, _, _) + | ty::Dynamic(_, _) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(_, _) diff --git a/compiler/rustc_public/src/ty.rs b/compiler/rustc_public/src/ty.rs index bcc77ff849da5..0afb94c18d7b9 100644 --- a/compiler/rustc_public/src/ty.rs +++ b/compiler/rustc_public/src/ty.rs @@ -333,7 +333,7 @@ impl TyKind { #[inline] pub fn is_trait(&self) -> bool { - matches!(self, TyKind::RigidTy(RigidTy::Dynamic(_, _, DynKind::Dyn))) + matches!(self, TyKind::RigidTy(RigidTy::Dynamic(_, _))) } #[inline] @@ -472,7 +472,7 @@ impl TyKind { } pub fn trait_principal(&self) -> Option> { - if let TyKind::RigidTy(RigidTy::Dynamic(predicates, _, _)) = self { + if let TyKind::RigidTy(RigidTy::Dynamic(predicates, _)) = self { if let Some(Binder { value: ExistentialPredicate::Trait(trait_ref), bound_vars }) = predicates.first() { @@ -562,7 +562,7 @@ pub enum RigidTy { Closure(ClosureDef, GenericArgs), Coroutine(CoroutineDef, GenericArgs), CoroutineClosure(CoroutineClosureDef, GenericArgs), - Dynamic(Vec>, Region, DynKind), + Dynamic(Vec>, Region), Never, Tuple(Vec), CoroutineWitness(CoroutineWitnessDef, GenericArgs), @@ -1206,11 +1206,6 @@ pub enum BoundRegionKind { BrEnv, } -#[derive(Clone, Debug, Eq, PartialEq, Serialize)] -pub enum DynKind { - Dyn, -} - #[derive(Clone, Debug, Eq, PartialEq, Serialize)] pub enum ExistentialPredicate { Trait(ExistentialTraitRef), diff --git a/compiler/rustc_public/src/unstable/convert/internal.rs b/compiler/rustc_public/src/unstable/convert/internal.rs index 66f767a98f5bd..dc9abd88614d3 100644 --- a/compiler/rustc_public/src/unstable/convert/internal.rs +++ b/compiler/rustc_public/src/unstable/convert/internal.rs @@ -14,7 +14,7 @@ use crate::mir::alloc::AllocId; use crate::mir::mono::{Instance, MonoItem, StaticDef}; use crate::mir::{BinOp, Mutability, Place, ProjectionElem, RawPtrKind, Safety, UnOp}; use crate::ty::{ - Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, DynKind, + Abi, AdtDef, Binder, BoundRegionKind, BoundTyKind, BoundVariableKind, ClosureKind, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FloatTy, FnSig, GenericArgKind, GenericArgs, IntTy, MirConst, Movability, Pattern, Region, RigidTy, Span, TermKind, TraitRef, Ty, TyConst, UintTy, VariantDef, VariantIdx, @@ -188,10 +188,9 @@ impl RustcInternal for RigidTy { def.0.internal(tables, tcx), args.internal(tables, tcx), ), - RigidTy::Dynamic(predicate, region, dyn_kind) => rustc_ty::TyKind::Dynamic( + RigidTy::Dynamic(predicate, region) => rustc_ty::TyKind::Dynamic( tcx.mk_poly_existential_predicates(&predicate.internal(tables, tcx)), region.internal(tables, tcx), - dyn_kind.internal(tables, tcx), ), RigidTy::Tuple(tys) => { rustc_ty::TyKind::Tuple(tcx.mk_type_list(&tys.internal(tables, tcx))) @@ -460,20 +459,6 @@ impl RustcInternal for BoundVariableKind { } } -impl RustcInternal for DynKind { - type T<'tcx> = rustc_ty::DynKind; - - fn internal<'tcx>( - &self, - _tables: &mut Tables<'_, BridgeTys>, - _tcx: impl InternalCx<'tcx>, - ) -> Self::T<'tcx> { - match self { - DynKind::Dyn => rustc_ty::DynKind::Dyn, - } - } -} - impl RustcInternal for ExistentialPredicate { type T<'tcx> = rustc_ty::ExistentialPredicate<'tcx>; diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index 5131611eb02b3..7f14f878d3737 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -48,16 +48,6 @@ impl<'tcx> Stable<'tcx> for ty::AliasTerm<'tcx> { } } -impl<'tcx> Stable<'tcx> for ty::DynKind { - type T = crate::ty::DynKind; - - fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { - match self { - ty::Dyn => crate::ty::DynKind::Dyn, - } - } -} - impl<'tcx> Stable<'tcx> for ty::ExistentialPredicate<'tcx> { type T = crate::ty::ExistentialPredicate; @@ -439,16 +429,13 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> { } // FIXME(unsafe_binders): ty::UnsafeBinder(_) => todo!(), - ty::Dynamic(existential_predicates, region, dyn_kind) => { - TyKind::RigidTy(RigidTy::Dynamic( - existential_predicates - .iter() - .map(|existential_predicate| existential_predicate.stable(tables, cx)) - .collect(), - region.stable(tables, cx), - dyn_kind.stable(tables, cx), - )) - } + ty::Dynamic(existential_predicates, region) => TyKind::RigidTy(RigidTy::Dynamic( + existential_predicates + .iter() + .map(|existential_predicate| existential_predicate.stable(tables, cx)) + .collect(), + region.stable(tables, cx), + )), ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure( tables.closure_def(*def_id), generic_args.stable(tables, cx), diff --git a/compiler/rustc_public/src/visitor.rs b/compiler/rustc_public/src/visitor.rs index 87f1cc6ae69d8..acc3334769613 100644 --- a/compiler/rustc_public/src/visitor.rs +++ b/compiler/rustc_public/src/visitor.rs @@ -171,7 +171,7 @@ impl Visitable for RigidTy { | RigidTy::CoroutineClosure(_, args) | RigidTy::FnDef(_, args) => args.visit(visitor), RigidTy::FnPtr(sig) => sig.visit(visitor), - RigidTy::Dynamic(pred, r, _) => { + RigidTy::Dynamic(pred, r) => { pred.visit(visitor)?; r.visit(visitor) } diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index f4a14b36ce5cf..ec7a4a81a71aa 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -626,12 +626,10 @@ pub(crate) fn encode_ty<'tcx>( } // Trait types - ty::Dynamic(predicates, region, kind) => { + ty::Dynamic(predicates, region) => { // u3dynIE, where is , as // vendor extended type. - let mut s = String::from(match kind { - ty::Dyn => "u3dynI", - }); + let mut s = String::from("u3dynI"); s.push_str(&encode_predicates(tcx, predicates, dict, options)); s.push_str(&encode_region(*region, dict)); s.push('E'); 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 577a16a0d2573..82a2a64f23078 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 @@ -268,7 +268,7 @@ fn trait_object_ty<'tcx>(tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tc let preds = tcx.mk_poly_existential_predicates_from_iter( iter::once(principal_pred).chain(assoc_preds.into_iter()), ); - Ty::new_dynamic(tcx, preds, tcx.lifetimes.re_erased, ty::Dyn) + Ty::new_dynamic(tcx, preds, tcx.lifetimes.re_erased) } /// Transforms an instance for LLVM CFI and cross-language LLVM CFI support using Itanium C++ ABI @@ -334,7 +334,7 @@ pub(crate) fn transform_instance<'tcx>( ty::List::empty(), )); let predicates = tcx.mk_poly_existential_predicates(&[ty::Binder::dummy(predicate)]); - let self_ty = Ty::new_dynamic(tcx, predicates, tcx.lifetimes.re_erased, ty::Dyn); + let self_ty = Ty::new_dynamic(tcx, predicates, tcx.lifetimes.re_erased); instance.args = tcx.mk_args_trait(self_ty, List::empty()); } else if let ty::InstanceKind::Virtual(def_id, _) = instance.def { // Transform self into a trait object of the trait that defines the method for virtual @@ -347,7 +347,7 @@ pub(crate) fn transform_instance<'tcx>( // drop_in_place won't have a defining trait, skip the upcast None => instance.args.type_at(0), }; - let ty::Dynamic(preds, lifetime, kind) = upcast_ty.kind() else { + let ty::Dynamic(preds, lifetime) = upcast_ty.kind() else { bug!("Tried to remove autotraits from non-dynamic type {upcast_ty}"); }; let self_ty = if preds.principal().is_some() { @@ -355,7 +355,7 @@ pub(crate) fn transform_instance<'tcx>( tcx.mk_poly_existential_predicates_from_iter(preds.into_iter().filter(|pred| { !matches!(pred.skip_binder(), ty::ExistentialPredicate::AutoTrait(..)) })); - Ty::new_dynamic(tcx, filtered_preds, *lifetime, *kind) + Ty::new_dynamic(tcx, filtered_preds, *lifetime) } else { // If there's no principal type, re-encode it as a unit, since we don't know anything // about it. This technically discards the knowledge that it was a type that was made diff --git a/compiler/rustc_symbol_mangling/src/export.rs b/compiler/rustc_symbol_mangling/src/export.rs index 76ac82cf95a12..3896e06a627b7 100644 --- a/compiler/rustc_symbol_mangling/src/export.rs +++ b/compiler/rustc_symbol_mangling/src/export.rs @@ -110,7 +110,7 @@ impl<'tcx> AbiHashStable<'tcx> for Ty<'tcx> { | ty::RawPtr(_, _) | ty::FnDef(_, _) | ty::FnPtr(_, _) - | ty::Dynamic(_, _, _) + | ty::Dynamic(_, _) | ty::Closure(_, _) | ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 1605b4958ba3d..9fa7e2f100393 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -577,10 +577,8 @@ impl<'tcx> Printer<'tcx> for V0SymbolMangler<'tcx> { // FIXME(unsafe_binder): ty::UnsafeBinder(..) => todo!(), - ty::Dynamic(predicates, r, kind) => { - self.push(match kind { - ty::Dyn => "D", - }); + ty::Dynamic(predicates, r) => { + self.push("D"); self.print_dyn_existential(predicates)?; r.print(self)?; } 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 3edc365c886ea..5b8315841765b 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 @@ -399,7 +399,7 @@ pub struct TraitObjectVisitor(pub FxIndexSet); impl<'tcx> TypeVisitor> for TraitObjectVisitor { fn visit_ty(&mut self, t: Ty<'tcx>) { match t.kind() { - ty::Dynamic(preds, re, _) if re.is_static() => { + ty::Dynamic(preds, re) if re.is_static() => { if let Some(def_id) = preds.principal_def_id() { self.0.insert(def_id); } 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 f997842a607f6..b0b858aa270c1 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 @@ -292,7 +292,7 @@ impl Trait for X { ); } } - (ty::Dynamic(t, _, ty::DynKind::Dyn), ty::Alias(ty::Opaque, alias)) + (ty::Dynamic(t, _), ty::Alias(ty::Opaque, alias)) if let Some(def_id) = t.principal_def_id() && tcx .explicit_item_self_bounds(alias.def_id) @@ -314,9 +314,7 @@ impl Trait for X { values.found, values.expected, )); } - (ty::Dynamic(t, _, ty::DynKind::Dyn), _) - if let Some(def_id) = t.principal_def_id() => - { + (ty::Dynamic(t, _), _) if let Some(def_id) = t.principal_def_id() => { let mut has_matching_impl = false; tcx.for_each_relevant_impl(def_id, values.found, |did| { if DeepRejectCtxt::relate_rigid_infer(tcx) @@ -335,9 +333,7 @@ impl Trait for X { )); } } - (_, ty::Dynamic(t, _, ty::DynKind::Dyn)) - if let Some(def_id) = t.principal_def_id() => - { + (_, ty::Dynamic(t, _)) if let Some(def_id) = t.principal_def_id() => { let mut has_matching_impl = false; tcx.for_each_relevant_impl(def_id, values.expected, |did| { if DeepRejectCtxt::relate_rigid_infer(tcx) @@ -489,7 +485,7 @@ impl Trait for X { && let Some(then) = blk.expr && def.is_box() && let boxed_ty = args.type_at(0) - && let ty::Dynamic(t, _, _) = boxed_ty.kind() + && let ty::Dynamic(t, _) = boxed_ty.kind() && let Some(def_id) = t.principal_def_id() && let mut impl_def_ids = vec![] && let _ = 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 518d4fe17e8f4..9a8ccea3aca87 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -430,7 +430,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut alt_span = None; if let Some(ty) = ty && sub.is_static() - && let ty::Dynamic(preds, _, ty::DynKind::Dyn) = ty.kind() + && let ty::Dynamic(preds, _) = ty.kind() && let Some(def_id) = preds.principal_def_id() { for (clause, span) in diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index f794ff632c592..b3d1b8e3888a1 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -554,7 +554,7 @@ fn attempt_dyn_to_enum_suggestion( // defaults to assuming that things are *not* sized, whereas we want to // fall back to assuming that things may be sized. match impl_type.kind() { - ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::DynKind::Dyn) => { + ty::Str | ty::Slice(_) | ty::Dynamic(_, _) => { return None; } _ => {} diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index bb5c6469f34b4..00c123981e1c0 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -237,7 +237,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } } - if let ty::Dynamic(traits, _, _) = self_ty.kind() { + if let ty::Dynamic(traits, _) = self_ty.kind() { for t in traits.iter() { if let ty::ExistentialPredicate::Trait(trait_ref) = t.skip_binder() { self_types.push(self.tcx.def_path_str(trait_ref.def_id)); 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 f2f840581cf02..37e622102e70f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1131,7 +1131,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }, ) } - ty::Dynamic(data, _, ty::Dyn) => data.iter().find_map(|pred| { + ty::Dynamic(data, _) => data.iter().find_map(|pred| { if let ty::ExistentialPredicate::Projection(proj) = pred.skip_binder() && self.tcx.is_lang_item(proj.def_id, LangItem::FnOnceOutput) // for existential projection, args are shifted over by 1 @@ -1520,7 +1520,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let ty::Ref(_, object_ty, hir::Mutability::Not) = target_ty.kind() else { return; }; - let ty::Dynamic(predicates, _, ty::Dyn) = object_ty.kind() else { + let ty::Dynamic(predicates, _) = object_ty.kind() else { return; }; let self_ref_ty = Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, self_ty); @@ -1883,7 +1883,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let ObligationCauseCode::SizedReturnType = obligation.cause.code() else { return false; }; - let ty::Dynamic(_, _, ty::Dyn) = trait_pred.self_ty().skip_binder().kind() else { + let ty::Dynamic(_, _) = trait_pred.self_ty().skip_binder().kind() else { return false; }; 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 62795c8a3a686..60f1fcb26c004 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -669,7 +669,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // These may potentially implement `FnPtr` ty::Placeholder(..) - | ty::Dynamic(_, _, _) + | ty::Dynamic(_, _) | ty::Alias(_, _) | ty::Infer(_) | ty::Param(..) @@ -991,7 +991,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match (source.kind(), target.kind()) { // Trait+Kx+'a -> Trait+Ky+'b (upcasts). - (&ty::Dynamic(a_data, a_region, ty::Dyn), &ty::Dynamic(b_data, b_region, ty::Dyn)) => { + (&ty::Dynamic(a_data, a_region), &ty::Dynamic(b_data, b_region)) => { // Upcast coercions permit several things: // // 1. Dropping auto traits, e.g., `Foo + Send` to `Foo` @@ -1054,7 +1054,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } // `T` -> `Trait` - (_, &ty::Dynamic(_, _, ty::Dyn)) => { + (_, &ty::Dynamic(_, _)) => { candidates.vec.push(BuiltinUnsizeCandidate); } @@ -1327,7 +1327,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Pat(_, _) | ty::FnPtr(..) | ty::UnsafeBinder(_) - | ty::Dynamic(_, _, _) + | ty::Dynamic(_, _) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Coroutine(_, _) diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 488094b15ac60..7ad65a1df8e9b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -1023,10 +1023,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let a_ty = self.infcx.shallow_resolve(predicate.self_ty()); let b_ty = self.infcx.shallow_resolve(predicate.trait_ref.args.type_at(1)); - let ty::Dynamic(a_data, a_region, ty::Dyn) = *a_ty.kind() else { + let ty::Dynamic(a_data, a_region) = *a_ty.kind() else { bug!("expected `dyn` type in `confirm_trait_upcasting_unsize_candidate`") }; - let ty::Dynamic(b_data, b_region, ty::Dyn) = *b_ty.kind() else { + let ty::Dynamic(b_data, b_region) = *b_ty.kind() else { bug!("expected `dyn` type in `confirm_trait_upcasting_unsize_candidate`") }; @@ -1062,10 +1062,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!(?source, ?target, "confirm_builtin_unsize_candidate"); Ok(match (source.kind(), target.kind()) { - // Trait+Kx+'a -> Trait+Ky+'b (auto traits and lifetime subtyping). - (&ty::Dynamic(data_a, r_a, dyn_a), &ty::Dynamic(data_b, r_b, dyn_b)) - if dyn_a == dyn_b => - { + // `dyn Trait + Kx + 'a` -> `dyn Trait + Ky + 'b` (auto traits and lifetime subtyping). + (&ty::Dynamic(data_a, r_a), &ty::Dynamic(data_b, r_b)) => { // See `assemble_candidates_for_unsizing` for more info. // We already checked the compatibility of auto traits within `assemble_candidates_for_unsizing`. let existential_predicates = if data_b.principal().is_some() { @@ -1098,7 +1096,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .map(ty::Binder::dummy), ) }; - let source_trait = Ty::new_dynamic(tcx, existential_predicates, r_b, dyn_a); + let source_trait = Ty::new_dynamic(tcx, existential_predicates, r_b); // Require that the traits involved in this upcast are **equal**; // only the **lifetime bound** is changed. @@ -1122,7 +1120,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } // `T` -> `dyn Trait` - (_, &ty::Dynamic(data, r, ty::Dyn)) => { + (_, &ty::Dynamic(data, r)) => { let mut object_dids = data.auto_traits().chain(data.principal_def_id()); if let Some(did) = object_dids.find(|did| !tcx.is_dyn_compatible(*did)) { return Err(SelectionError::TraitDynIncompatible(did)); diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index 7e8a41457d411..584c8e2a27c82 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -317,7 +317,7 @@ pub(crate) fn first_method_vtable_slot<'tcx>(tcx: TyCtxt<'tcx>, key: ty::TraitRe "vtable trait ref should be normalized" ); - let ty::Dynamic(source, _, _) = *key.self_ty().kind() else { + let ty::Dynamic(source, _) = *key.self_ty().kind() else { bug!(); }; let source_principal = tcx.instantiate_bound_regions_with_erased( @@ -384,13 +384,13 @@ pub(crate) fn supertrait_vtable_slot<'tcx>( let (source, target) = key; // If the target principal is `None`, we can just return `None`. - let ty::Dynamic(target_data, _, _) = *target.kind() else { + let ty::Dynamic(target_data, _) = *target.kind() else { bug!(); }; let target_principal = tcx.instantiate_bound_regions_with_erased(target_data.principal()?); // Given that we have a target principal, it is a bug for there not to be a source principal. - let ty::Dynamic(source_data, _, _) = *source.kind() else { + let ty::Dynamic(source_data, _) = *source.kind() else { bug!(); }; let source_principal = tcx.instantiate_bound_regions_with_erased( diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index adce9850b594c..45cbb56b1c2ef 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -915,7 +915,7 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { // We recurse into the binder below. } - ty::Dynamic(data, r, _) => { + ty::Dynamic(data, r) => { // WfObject // // Here, we defer WF checking due to higher-ranked diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 79f7e228e2adc..643e3db8f83fe 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -476,7 +476,7 @@ fn layout_of_uncached<'tcx>( } // Odd unit types. - ty::FnDef(..) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => { + ty::FnDef(..) | ty::Dynamic(_, _) | ty::Foreign(..) => { let sized = matches!(ty.kind(), ty::FnDef(..)); tcx.mk_layout(LayoutData::unit(cx, sized)) } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index a5987757dc34d..18a9a7c22d9dd 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -40,7 +40,7 @@ fn sizedness_constraint_for_ty<'tcx>( | ty::CoroutineWitness(..) | ty::Never => None, - ty::Str | ty::Slice(..) | ty::Dynamic(_, _, ty::Dyn) => match sizedness { + ty::Str | ty::Slice(..) | ty::Dynamic(_, _) => match sizedness { // Never `Sized` SizedTraitKind::Sized => Some(ty), // Always `MetaSized` @@ -366,7 +366,7 @@ fn impl_self_is_guaranteed_unsized<'tcx>(tcx: TyCtxt<'tcx>, impl_def_id: DefId) ); match tail.kind() { - ty::Dynamic(_, _, ty::Dyn) | ty::Slice(_) | ty::Str => true, + ty::Dynamic(_, _) | ty::Slice(_) | ty::Str => true, ty::Bool | ty::Char | ty::Int(_) diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 23b7f55fbbe53..24704c5bb5358 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -288,7 +288,7 @@ impl FlagComputation { self.add_alias_ty(data); } - ty::Dynamic(obj, r, _) => { + ty::Dynamic(obj, r) => { for predicate in obj.iter() { self.bound_computation(predicate, |computation, predicate| match predicate { ty::ExistentialPredicate::Trait(tr) => { diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index ecfc05a6e20e7..b5b552dbaec09 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -76,12 +76,7 @@ pub trait Ty>: fn new_foreign(interner: I, def_id: I::ForeignId) -> Self; - fn new_dynamic( - interner: I, - preds: I::BoundExistentialPredicates, - region: I::Region, - kind: ty::DynKind, - ) -> Self; + fn new_dynamic(interner: I, preds: I::BoundExistentialPredicates, region: I::Region) -> Self; fn new_coroutine(interner: I, def_id: I::CoroutineId, args: I::GenericArgs) -> Self; @@ -167,7 +162,7 @@ pub trait Ty>: fn is_guaranteed_unsized_raw(self) -> bool { match self.kind() { - ty::Dynamic(_, _, ty::Dyn) | ty::Slice(_) | ty::Str => true, + ty::Dynamic(_, _) | ty::Slice(_) | ty::Str => true, ty::Bool | ty::Char | ty::Int(_) diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 50b588029aed9..61e0b67b1639d 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -57,7 +57,6 @@ mod upcast; mod visit; pub use AliasTyKind::*; -pub use DynKind::*; pub use InferTy::*; pub use RegionKind::*; pub use TyKind::*; diff --git a/compiler/rustc_type_ir/src/outlives.rs b/compiler/rustc_type_ir/src/outlives.rs index b09a378d34143..c7dccea6adc12 100644 --- a/compiler/rustc_type_ir/src/outlives.rs +++ b/compiler/rustc_type_ir/src/outlives.rs @@ -203,7 +203,7 @@ impl TypeVisitor for OutlivesCollector<'_, I> { | ty::Ref(_, _, _) | ty::FnPtr(..) | ty::UnsafeBinder(_) - | ty::Dynamic(_, _, _) + | ty::Dynamic(_, _) | ty::Tuple(_) => { ty.super_visit_with(self); } diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 690a5f65e0848..09add529286d9 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -412,16 +412,11 @@ pub fn structurally_relate_tys>( (ty::Foreign(a_id), ty::Foreign(b_id)) if a_id == b_id => Ok(Ty::new_foreign(cx, a_id)), - (ty::Dynamic(a_obj, a_region, a_repr), ty::Dynamic(b_obj, b_region, b_repr)) - if a_repr == b_repr => - { - Ok(Ty::new_dynamic( - cx, - relation.relate(a_obj, b_obj)?, - relation.relate(a_region, b_region)?, - a_repr, - )) - } + (ty::Dynamic(a_obj, a_region), ty::Dynamic(b_obj, b_region)) => Ok(Ty::new_dynamic( + cx, + relation.relate(a_obj, b_obj)?, + relation.relate(a_region, b_region)?, + )), (ty::Coroutine(a_id, a_args), ty::Coroutine(b_id, b_args)) if a_id == b_id => { // All Coroutine types with the same id represent diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 225d85f79c3d1..dda59283677cd 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -19,20 +19,6 @@ use crate::{self as ty, DebruijnIndex, FloatTy, IntTy, Interner, UintTy}; mod closure; -/// Specifies how a trait object is represented. -/// -/// This used to have a variant `DynStar`, but that variant has been removed, -/// and it's likely this whole enum will be removed soon. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[cfg_attr( - feature = "nightly", - derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext) -)] -pub enum DynKind { - /// An unsized `dyn Trait` object - Dyn, -} - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[cfg_attr( feature = "nightly", @@ -165,7 +151,7 @@ pub enum TyKind { UnsafeBinder(UnsafeBinderInner), /// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`. - Dynamic(I::BoundExistentialPredicates, I::Region, DynKind), + Dynamic(I::BoundExistentialPredicates, I::Region), /// The anonymous type of a closure. Used to represent the type of `|a| a`. /// @@ -314,7 +300,7 @@ impl TyKind { | ty::FnDef(_, _) | ty::FnPtr(..) | ty::UnsafeBinder(_) - | ty::Dynamic(_, _, _) + | ty::Dynamic(_, _) | ty::Closure(_, _) | ty::CoroutineClosure(_, _) | ty::Coroutine(_, _) @@ -367,9 +353,7 @@ impl fmt::Debug for TyKind { FnPtr(sig_tys, hdr) => write!(f, "{:?}", sig_tys.with(*hdr)), // FIXME(unsafe_binder): print this like `unsafe<'a> T<'a>`. UnsafeBinder(binder) => write!(f, "{:?}", binder), - Dynamic(p, r, repr) => match repr { - DynKind::Dyn => write!(f, "dyn {p:?} + {r:?}"), - }, + Dynamic(p, r) => write!(f, "dyn {p:?} + {r:?}"), Closure(d, s) => f.debug_tuple("Closure").field(d).field(&s).finish(), CoroutineClosure(d, s) => f.debug_tuple("CoroutineClosure").field(d).field(&s).finish(), Coroutine(d, s) => f.debug_tuple("Coroutine").field(d).field(&s).finish(), diff --git a/compiler/rustc_type_ir/src/walk.rs b/compiler/rustc_type_ir/src/walk.rs index 9912fad1756ea..6d51817a7bf44 100644 --- a/compiler/rustc_type_ir/src/walk.rs +++ b/compiler/rustc_type_ir/src/walk.rs @@ -109,7 +109,7 @@ fn push_inner(stack: &mut TypeWalkerStack, parent: I::GenericArg ty::Alias(_, data) => { stack.extend(data.args.iter().rev()); } - ty::Dynamic(obj, lt, _) => { + ty::Dynamic(obj, lt) => { stack.push(lt.into()); stack.extend( obj.iter() diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 5ccacafea0158..0afb969d5c84f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2093,7 +2093,7 @@ pub(crate) fn clean_middle_ty<'tcx>( ); Type::Path { path } } - ty::Dynamic(obj, reg, _) => { + ty::Dynamic(obj, reg) => { // HACK: pick the first `did` as the `did` of the trait object. Someone // might want to implement "native" support for marker-trait-only // trait objects. diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 68f0b5ea25589..ac87e21b82f15 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -86,7 +86,7 @@ fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span, msrv: Msrv) ty::FnPtr(..) => { return Err((span, "function pointers in const fn are unstable".into())); }, - ty::Dynamic(preds, _, _) => { + ty::Dynamic(preds, _) => { for pred in *preds { match pred.skip_binder() { ty::ExistentialPredicate::AutoTrait(_) | ty::ExistentialPredicate::Projection(_) => { diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index 9f77a1c4d9b62..3e41bce1dc4ce 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -349,7 +349,7 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { } false }, - ty::Dynamic(binder, _, _) => { + ty::Dynamic(binder, _) => { for predicate in *binder { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() && find_attr!(cx.tcx.get_all_attrs(trait_ref.def_id), AttributeKind::MustUse { .. }) @@ -673,7 +673,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option Some(ExprFnSig::Sig(sig_tys.with(hdr), None)), - ty::Dynamic(bounds, _, _) => { + ty::Dynamic(bounds, _) => { let lang_items = cx.tcx.lang_items(); match bounds.principal() { Some(bound)