From 1d74589facef77f9f72b5d7a9917a174ca30c2c8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 3 Feb 2024 18:39:24 +0000 Subject: [PATCH 1/5] Assert that ParamTy and ParamConst have identical names for identical indices --- compiler/rustc_middle/src/ty/relate.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index f2321e7e1d22f..29d5e5b2b9bbc 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -435,7 +435,10 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( Ok(a) } - (ty::Param(a_p), ty::Param(b_p)) if a_p.index == b_p.index => Ok(a), + (ty::Param(a_p), ty::Param(b_p)) if a_p.index == b_p.index => { + debug_assert_eq!(a_p.name, b_p.name, "param types with same index differ in name"); + Ok(a) + }, (ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a), @@ -593,7 +596,10 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>( (ty::ConstKind::Error(_), _) => return Ok(a), (_, ty::ConstKind::Error(_)) => return Ok(b), - (ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) => a_p.index == b_p.index, + (ty::ConstKind::Param(a_p), ty::ConstKind::Param(b_p)) if a_p.index == b_p.index => { + debug_assert_eq!(a_p.name, b_p.name, "param types with same index differ in name"); + true + } (ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2, (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => a_val == b_val, From 623bd5843b9ff20bba6bbaf23110317992a8e329 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 3 Feb 2024 18:52:30 +0000 Subject: [PATCH 2/5] Do not create param types that differ only by name when comparing intrinsic signatures --- .../rustc_hir_analysis/src/check/intrinsic.rs | 25 ++++++++++++++++--- compiler/rustc_middle/src/ty/relate.rs | 2 +- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 2d0d6611444c5..7f12ce1acf5e9 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -12,7 +12,7 @@ use rustc_errors::{codes::*, struct_span_code_err, DiagnosticMessage}; use rustc_hir as hir; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::symbol::{kw, sym}; use rustc_target::spec::abi::Abi; fn equate_intrinsic_type<'tcx>( @@ -132,7 +132,17 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: DefId) -> hir /// Remember to add all intrinsics here, in `compiler/rustc_codegen_llvm/src/intrinsic.rs`, /// and in `library/core/src/intrinsics.rs`. pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { - let param = |n| Ty::new_param(tcx, n, Symbol::intern(&format!("P{n}"))); + let generics = tcx.generics_of(it.owner_id); + let param = |n| { + if let Some(&ty::GenericParamDef { + name, kind: ty::GenericParamDefKind::Type { .. }, .. + }) = generics.opt_param_at(n as usize, tcx) + { + Ty::new_param(tcx, n, name) + } else { + Ty::new_error_with_message(tcx, tcx.def_span(it.owner_id), "expected param") + } + }; let intrinsic_id = it.owner_id.to_def_id(); let intrinsic_name = tcx.item_name(intrinsic_id); let name_str = intrinsic_name.as_str(); @@ -475,9 +485,16 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { /// Type-check `extern "platform-intrinsic" { ... }` functions. pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { + let generics = tcx.generics_of(it.owner_id); let param = |n| { - let name = Symbol::intern(&format!("P{n}")); - Ty::new_param(tcx, n, name) + if let Some(&ty::GenericParamDef { + name, kind: ty::GenericParamDefKind::Type { .. }, .. + }) = generics.opt_param_at(n as usize, tcx) + { + Ty::new_param(tcx, n, name) + } else { + Ty::new_error_with_message(tcx, tcx.def_span(it.owner_id), "expected param") + } }; let name = it.ident.name; diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 29d5e5b2b9bbc..303f285b00c7b 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -438,7 +438,7 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>( (ty::Param(a_p), ty::Param(b_p)) if a_p.index == b_p.index => { debug_assert_eq!(a_p.name, b_p.name, "param types with same index differ in name"); Ok(a) - }, + } (ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a), From ab7d207689d88d533b03c44a80ce64bd477ce9f1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 5 Feb 2024 17:43:28 +0000 Subject: [PATCH 3/5] Use correct param env when building and cleaning items in librustdoc --- src/librustdoc/clean/inline.rs | 56 +++++++++++++------- src/librustdoc/clean/mod.rs | 4 +- src/librustdoc/clean/utils.rs | 8 ++- src/librustdoc/passes/collect_trait_impls.rs | 12 +++-- 4 files changed, 56 insertions(+), 24 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index aab974ad79edd..08f5fe1f55a71 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -65,37 +65,49 @@ pub(crate) fn try_inline( let kind = match res { Res::Def(DefKind::Trait, did) => { record_extern_fqn(cx, did, ItemType::Trait); - build_impls(cx, did, attrs_without_docs, &mut ret); - clean::TraitItem(Box::new(build_external_trait(cx, did))) + cx.with_param_env(did, |cx| { + build_impls(cx, did, attrs_without_docs, &mut ret); + clean::TraitItem(Box::new(build_external_trait(cx, did))) + }) } Res::Def(DefKind::Fn, did) => { record_extern_fqn(cx, did, ItemType::Function); - clean::FunctionItem(build_external_function(cx, did)) + cx.with_param_env(did, |cx| clean::FunctionItem(build_external_function(cx, did))) } Res::Def(DefKind::Struct, did) => { record_extern_fqn(cx, did, ItemType::Struct); - build_impls(cx, did, attrs_without_docs, &mut ret); - clean::StructItem(build_struct(cx, did)) + cx.with_param_env(did, |cx| { + build_impls(cx, did, attrs_without_docs, &mut ret); + clean::StructItem(build_struct(cx, did)) + }) } Res::Def(DefKind::Union, did) => { record_extern_fqn(cx, did, ItemType::Union); - build_impls(cx, did, attrs_without_docs, &mut ret); - clean::UnionItem(build_union(cx, did)) + cx.with_param_env(did, |cx| { + build_impls(cx, did, attrs_without_docs, &mut ret); + clean::UnionItem(build_union(cx, did)) + }) } Res::Def(DefKind::TyAlias, did) => { record_extern_fqn(cx, did, ItemType::TypeAlias); - build_impls(cx, did, attrs_without_docs, &mut ret); - clean::TypeAliasItem(build_type_alias(cx, did, &mut ret)) + cx.with_param_env(did, |cx| { + build_impls(cx, did, attrs_without_docs, &mut ret); + clean::TypeAliasItem(build_type_alias(cx, did, &mut ret)) + }) } Res::Def(DefKind::Enum, did) => { record_extern_fqn(cx, did, ItemType::Enum); - build_impls(cx, did, attrs_without_docs, &mut ret); - clean::EnumItem(build_enum(cx, did)) + cx.with_param_env(did, |cx| { + build_impls(cx, did, attrs_without_docs, &mut ret); + clean::EnumItem(build_enum(cx, did)) + }) } Res::Def(DefKind::ForeignTy, did) => { record_extern_fqn(cx, did, ItemType::ForeignType); - build_impls(cx, did, attrs_without_docs, &mut ret); - clean::ForeignTypeItem + cx.with_param_env(did, |cx| { + build_impls(cx, did, attrs_without_docs, &mut ret); + clean::ForeignTypeItem + }) } // Never inline enum variants but leave them shown as re-exports. Res::Def(DefKind::Variant, _) => return None, @@ -108,11 +120,13 @@ pub(crate) fn try_inline( } Res::Def(DefKind::Static(_), did) => { record_extern_fqn(cx, did, ItemType::Static); - clean::StaticItem(build_static(cx, did, cx.tcx.is_mutable_static(did))) + cx.with_param_env(did, |cx| { + clean::StaticItem(build_static(cx, did, cx.tcx.is_mutable_static(did))) + }) } Res::Def(DefKind::Const, did) => { record_extern_fqn(cx, did, ItemType::Constant); - clean::ConstantItem(build_const(cx, did)) + cx.with_param_env(did, |cx| clean::ConstantItem(build_const(cx, did))) } Res::Def(DefKind::Macro(kind), did) => { let mac = build_macro(cx, did, name, import_def_id, kind); @@ -313,7 +327,9 @@ pub(crate) fn build_impls( // for each implementation of an item represented by `did`, build the clean::Item for that impl for &did in tcx.inherent_impls(did).into_iter().flatten() { - build_impl(cx, did, attrs, ret); + cx.with_param_env(did, |cx| { + build_impl(cx, did, attrs, ret); + }); } // This pretty much exists expressly for `dyn Error` traits that exist in the `alloc` crate. @@ -326,7 +342,9 @@ pub(crate) fn build_impls( let type_ = if tcx.is_trait(did) { SimplifiedType::Trait(did) } else { SimplifiedType::Adt(did) }; for &did in tcx.incoherent_impls(type_).into_iter().flatten() { - build_impl(cx, did, attrs, ret); + cx.with_param_env(did, |cx| { + build_impl(cx, did, attrs, ret); + }); } } } @@ -528,7 +546,9 @@ pub(crate) fn build_impl( } if let Some(did) = trait_.as_ref().map(|t| t.def_id()) { - record_extern_trait(cx, did); + cx.with_param_env(did, |cx| { + record_extern_trait(cx, did); + }); } let (merged_attrs, cfg) = merge_attrs(cx, load_attrs(cx, did), attrs); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3bac71dbc24e2..1f2a9c0a17a7e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -947,7 +947,9 @@ fn clean_ty_alias_inner_type<'tcx>( }; if !adt_def.did().is_local() { - inline::build_impls(cx, adt_def.did(), None, ret); + cx.with_param_env(adt_def.did(), |cx| { + inline::build_impls(cx, adt_def.did(), None, ret); + }); } Some(if adt_def.is_enum() { diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index b2b20c95a7e6a..0b7d35d7be4c8 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -295,12 +295,16 @@ pub(crate) fn build_deref_target_impls( if let Some(prim) = target.primitive_type() { let _prof_timer = tcx.sess.prof.generic_activity("build_primitive_inherent_impls"); for did in prim.impls(tcx).filter(|did| !did.is_local()) { - inline::build_impl(cx, did, None, ret); + cx.with_param_env(did, |cx| { + inline::build_impl(cx, did, None, ret); + }); } } else if let Type::Path { path } = target { let did = path.def_id(); if !did.is_local() { - inline::build_impls(cx, did, None, ret); + cx.with_param_env(did, |cx| { + inline::build_impls(cx, did, None, ret); + }); } } } diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index e2a7ef8556ea6..53c08ef5e5ca5 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -49,7 +49,9 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> let _prof_timer = tcx.sess.prof.generic_activity("build_extern_trait_impls"); for &cnum in tcx.crates(()) { for &impl_def_id in tcx.trait_impls_in_crate(cnum) { - inline::build_impl(cx, impl_def_id, None, &mut new_items_external); + cx.with_param_env(impl_def_id, |cx| { + inline::build_impl(cx, impl_def_id, None, &mut new_items_external); + }); } } } @@ -74,7 +76,9 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> ); parent = tcx.opt_parent(did); } - inline::build_impl(cx, impl_def_id, Some((&attr_buf, None)), &mut new_items_local); + cx.with_param_env(impl_def_id, |cx| { + inline::build_impl(cx, impl_def_id, Some((&attr_buf, None)), &mut new_items_local); + }); attr_buf.clear(); } } @@ -83,7 +87,9 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> for def_id in PrimitiveType::all_impls(tcx) { // Try to inline primitive impls from other crates. if !def_id.is_local() { - inline::build_impl(cx, def_id, None, &mut new_items_external); + cx.with_param_env(def_id, |cx| { + inline::build_impl(cx, def_id, None, &mut new_items_external); + }); } } for (prim, did) in PrimitiveType::primitive_locations(tcx) { From eb7a0f8eb65908abd173ecba0ac13738ba3697d7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 7 Feb 2024 17:17:52 +0000 Subject: [PATCH 4/5] Use correct param env in clippy --- src/tools/clippy/clippy_lints/src/default.rs | 4 ++-- src/tools/clippy/clippy_lints/src/useless_conversion.rs | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs index d8a070b785d5d..8789efcc99444 100644 --- a/src/tools/clippy/clippy_lints/src/default.rs +++ b/src/tools/clippy/clippy_lints/src/default.rs @@ -131,7 +131,7 @@ impl<'tcx> LateLintPass<'tcx> for Default { // only when assigning `... = Default::default()` && is_expr_default(expr, cx) && let binding_type = cx.typeck_results().node_type(binding_id) - && let Some(adt) = binding_type.ty_adt_def() + && let ty::Adt(adt, args) = *binding_type.kind() && adt.is_struct() && let variant = adt.non_enum_variant() && (adt.did().is_local() || !variant.is_field_list_non_exhaustive()) @@ -144,7 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for Default { .fields .iter() .all(|field| { - is_copy(cx, cx.tcx.type_of(field.did).instantiate_identity()) + is_copy(cx, cx.tcx.type_of(field.did).instantiate(cx.tcx, args)) }) && (!has_drop(cx, binding_type) || all_fields_are_copy) { diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs index 2e0a0f6cb3e45..f7a455977facd 100644 --- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs +++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs @@ -86,7 +86,6 @@ fn into_iter_bound<'tcx>( param_index: u32, node_args: GenericArgsRef<'tcx>, ) -> Option { - let param_env = cx.tcx.param_env(fn_did); let mut into_iter_span = None; for (pred, span) in cx.tcx.explicit_predicates_of(fn_did).predicates { @@ -111,7 +110,7 @@ fn into_iter_bound<'tcx>( })); let predicate = EarlyBinder::bind(tr).instantiate(cx.tcx, args); - let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), param_env, predicate); + let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate); if !cx .tcx .infer_ctxt() From 24d806ccfa0842f5b65f90a9145fd2439d5c4d34 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 7 Feb 2024 20:14:35 +0000 Subject: [PATCH 5/5] Stop using is_copy_modulo_regions when building clone shim --- compiler/rustc_mir_transform/src/shim.rs | 5 +---- compiler/rustc_ty_utils/src/instance.rs | 4 +--- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 7b6de3a543955..860d280be2950 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -447,16 +447,13 @@ fn build_thread_local_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'t fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> { debug!("build_clone_shim(def_id={:?})", def_id); - let param_env = tcx.param_env_reveal_all_normalized(def_id); - let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty); - let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env); let dest = Place::return_place(); let src = tcx.mk_place_deref(Place::from(Local::new(1 + 0))); match self_ty.kind() { - _ if is_copy => builder.copy_shim(), + ty::FnDef(..) | ty::FnPtr(_) => builder.copy_shim(), ty::Closure(_, args) => builder.tuple_like_shim(dest, src, args.as_closure().upvar_tys()), ty::Tuple(..) => builder.tuple_like_shim(dest, src, self_ty.tuple_fields()), ty::Coroutine(coroutine_def_id, args) => { diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 9faad10dd14df..f47791991a98f 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -209,10 +209,8 @@ fn resolve_associated_item<'tcx>( let name = tcx.item_name(trait_item_id); if name == sym::clone { let self_ty = trait_ref.self_ty(); - - let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env); match self_ty.kind() { - _ if is_copy => (), + ty::FnDef(..) | ty::FnPtr(_) => (), ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Closure(..)