diff options
| author | bors <bors@rust-lang.org> | 2024-03-31 05:44:17 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-03-31 05:44:17 +0000 |
| commit | d5de305fef8065d3af726537db2513a884ed2bcc (patch) | |
| tree | 70ea36b7fd5f777449cc0622edc1f960490a2747 /compiler | |
| parent | 723acede108580cdd6a848342ef3049f687f197e (diff) | |
| parent | eb8e8c06b6c6ab90b6ecbed1ac3820304c53ef01 (diff) | |
Auto merge of #3435 - rust-lang:rustup-2024-03-31, r=saethlin
Automatic Rustup
Diffstat (limited to 'compiler')
19 files changed, 348 insertions, 279 deletions
diff --git a/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch b/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch index 914ae986b50..36d0789d2a2 100644 --- a/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch +++ b/compiler/rustc_codegen_gcc/patches/libgccjit12/0001-core-Disable-portable-simd-test.patch @@ -14,7 +14,7 @@ index d0a119c..76fdece 100644 @@ -89,7 +89,6 @@ #![feature(never_type)] #![feature(unwrap_infallible)] - #![feature(pointer_is_aligned)] + #![feature(pointer_is_aligned_to)] -#![feature(portable_simd)] #![feature(ptr_metadata)] #![feature(lazy_cell)] @@ -27,6 +27,6 @@ index d0a119c..76fdece 100644 mod slice; mod str; mod str_lossy; --- +-- 2.42.1 diff --git a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs index ff4208def31..8b9e834b60b 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs @@ -243,6 +243,7 @@ where T: Tag, { #[inline] + #[allow(ambiguous_wide_pointer_comparisons)] fn eq(&self, other: &Self) -> bool { self.packed == other.packed } diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 9bf4d63267a..d8a90d62dac 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -295,6 +295,8 @@ hir_analysis_not_supported_delegation = {$descr} is not supported yet .label = callee defined here +hir_analysis_only_current_traits_adt = `{$name}` is not defined in the current crate + hir_analysis_only_current_traits_arbitrary = only traits defined in the current crate can be implemented for arbitrary types hir_analysis_only_current_traits_foreign = this is not defined in the current crate because this is a foreign trait diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index ca8a635ab5e..1770f7b4e91 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -4,7 +4,7 @@ use crate::errors; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; -use rustc_middle::ty::{self, AliasKind, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, AliasKind, TyCtxt, TypeVisitableExt}; use rustc_span::def_id::LocalDefId; use rustc_span::Span; use rustc_trait_selection::traits::{self, IsFirstInputType}; @@ -283,9 +283,14 @@ fn emit_orphan_check_error<'tcx>( let self_ty = trait_ref.self_ty(); Err(match err { traits::OrphanCheckErr::NonLocalInputType(tys) => { - let (mut opaque, mut foreign, mut name, mut pointer, mut ty_diag) = - (Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new()); - let mut sugg = None; + let mut diag = tcx.dcx().create_err(match self_ty.kind() { + ty::Adt(..) => errors::OnlyCurrentTraits::Outside { span: sp, note: () }, + _ if self_ty.is_primitive() => { + errors::OnlyCurrentTraits::Primitive { span: sp, note: () } + } + _ => errors::OnlyCurrentTraits::Arbitrary { span: sp, note: () }, + }); + for &(mut ty, is_target_ty) in &tys { let span = if matches!(is_target_ty, IsFirstInputType::Yes) { // Point at `D<A>` in `impl<A, B> for C<B> in D<A>` @@ -296,113 +301,86 @@ fn emit_orphan_check_error<'tcx>( }; ty = tcx.erase_regions(ty); - ty = match ty.kind() { - // Remove the type arguments from the output, as they are not relevant. - // You can think of this as the reverse of `resolve_vars_if_possible`. - // That way if we had `Vec<MyType>`, we will properly attribute the - // problem to `Vec<T>` and avoid confusing the user if they were to see - // `MyType` in the error. - ty::Adt(def, _) => Ty::new_adt(tcx, *def, ty::List::empty()), - _ => ty, - }; - - fn push_to_foreign_or_name<'tcx>( - is_foreign: bool, - foreign: &mut Vec<errors::OnlyCurrentTraitsForeign>, - name: &mut Vec<errors::OnlyCurrentTraitsName<'tcx>>, - span: Span, - sname: &'tcx str, - ) { - if is_foreign { - foreign.push(errors::OnlyCurrentTraitsForeign { span }) - } else { - name.push(errors::OnlyCurrentTraitsName { span, name: sname }); - } - } let is_foreign = !trait_ref.def_id.is_local() && matches!(is_target_ty, IsFirstInputType::No); match *ty.kind() { ty::Slice(_) => { - push_to_foreign_or_name( - is_foreign, - &mut foreign, - &mut name, - span, - "slices", - ); + if is_foreign { + diag.subdiagnostic( + tcx.dcx(), + errors::OnlyCurrentTraitsForeign { span }, + ); + } else { + diag.subdiagnostic( + tcx.dcx(), + errors::OnlyCurrentTraitsName { span, name: "slices" }, + ); + } } ty::Array(..) => { - push_to_foreign_or_name( - is_foreign, - &mut foreign, - &mut name, - span, - "arrays", - ); + if is_foreign { + diag.subdiagnostic( + tcx.dcx(), + errors::OnlyCurrentTraitsForeign { span }, + ); + } else { + diag.subdiagnostic( + tcx.dcx(), + errors::OnlyCurrentTraitsName { span, name: "arrays" }, + ); + } } ty::Tuple(..) => { - push_to_foreign_or_name( - is_foreign, - &mut foreign, - &mut name, - span, - "tuples", - ); + if is_foreign { + diag.subdiagnostic( + tcx.dcx(), + errors::OnlyCurrentTraitsForeign { span }, + ); + } else { + diag.subdiagnostic( + tcx.dcx(), + errors::OnlyCurrentTraitsName { span, name: "tuples" }, + ); + } } ty::Alias(ty::Opaque, ..) => { - opaque.push(errors::OnlyCurrentTraitsOpaque { span }) + diag.subdiagnostic(tcx.dcx(), errors::OnlyCurrentTraitsOpaque { span }); } ty::RawPtr(ptr_ty, mutbl) => { if !self_ty.has_param() { - let mut_key = mutbl.prefix_str(); - sugg = Some(errors::OnlyCurrentTraitsPointerSugg { - wrapper_span: self_ty_span, - struct_span: full_impl_span.shrink_to_lo(), - mut_key, - ptr_ty, - }); + diag.subdiagnostic( + tcx.dcx(), + errors::OnlyCurrentTraitsPointerSugg { + wrapper_span: self_ty_span, + struct_span: full_impl_span.shrink_to_lo(), + mut_key: mutbl.prefix_str(), + ptr_ty, + }, + ); } - pointer.push(errors::OnlyCurrentTraitsPointer { span, pointer: ty }); + diag.subdiagnostic( + tcx.dcx(), + errors::OnlyCurrentTraitsPointer { span, pointer: ty }, + ); + } + ty::Adt(adt_def, _) => { + diag.subdiagnostic( + tcx.dcx(), + errors::OnlyCurrentTraitsAdt { + span, + name: tcx.def_path_str(adt_def.did()), + }, + ); + } + _ => { + diag.subdiagnostic(tcx.dcx(), errors::OnlyCurrentTraitsTy { span, ty }); } - _ => ty_diag.push(errors::OnlyCurrentTraitsTy { span, ty }), } } - let err_struct = match self_ty.kind() { - ty::Adt(..) => errors::OnlyCurrentTraits::Outside { - span: sp, - note: (), - opaque, - foreign, - name, - pointer, - ty: ty_diag, - sugg, - }, - _ if self_ty.is_primitive() => errors::OnlyCurrentTraits::Primitive { - span: sp, - note: (), - opaque, - foreign, - name, - pointer, - ty: ty_diag, - sugg, - }, - _ => errors::OnlyCurrentTraits::Arbitrary { - span: sp, - note: (), - opaque, - foreign, - name, - pointer, - ty: ty_diag, - sugg, - }, - }; - tcx.dcx().emit_err(err_struct) + diag.emit() } traits::OrphanCheckErr::UncoveredTy(param_ty, local_type) => { let mut sp = sp; diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index fb919714afd..2d4742fa1dc 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1376,7 +1376,7 @@ pub struct TyParamSome<'a> { } #[derive(Diagnostic)] -pub enum OnlyCurrentTraits<'a> { +pub enum OnlyCurrentTraits { #[diag(hir_analysis_only_current_traits_outside, code = E0117)] Outside { #[primary_span] @@ -1384,18 +1384,6 @@ pub enum OnlyCurrentTraits<'a> { span: Span, #[note(hir_analysis_only_current_traits_note)] note: (), - #[subdiagnostic] - opaque: Vec<OnlyCurrentTraitsOpaque>, - #[subdiagnostic] - foreign: Vec<OnlyCurrentTraitsForeign>, - #[subdiagnostic] - name: Vec<OnlyCurrentTraitsName<'a>>, - #[subdiagnostic] - pointer: Vec<OnlyCurrentTraitsPointer<'a>>, - #[subdiagnostic] - ty: Vec<OnlyCurrentTraitsTy<'a>>, - #[subdiagnostic] - sugg: Option<OnlyCurrentTraitsPointerSugg<'a>>, }, #[diag(hir_analysis_only_current_traits_primitive, code = E0117)] Primitive { @@ -1404,18 +1392,6 @@ pub enum OnlyCurrentTraits<'a> { span: Span, #[note(hir_analysis_only_current_traits_note)] note: (), - #[subdiagnostic] - opaque: Vec<OnlyCurrentTraitsOpaque>, - #[subdiagnostic] - foreign: Vec<OnlyCurrentTraitsForeign>, - #[subdiagnostic] - name: Vec<OnlyCurrentTraitsName<'a>>, - #[subdiagnostic] - pointer: Vec<OnlyCurrentTraitsPointer<'a>>, - #[subdiagnostic] - ty: Vec<OnlyCurrentTraitsTy<'a>>, - #[subdiagnostic] - sugg: Option<OnlyCurrentTraitsPointerSugg<'a>>, }, #[diag(hir_analysis_only_current_traits_arbitrary, code = E0117)] Arbitrary { @@ -1424,18 +1400,6 @@ pub enum OnlyCurrentTraits<'a> { span: Span, #[note(hir_analysis_only_current_traits_note)] note: (), - #[subdiagnostic] - opaque: Vec<OnlyCurrentTraitsOpaque>, - #[subdiagnostic] - foreign: Vec<OnlyCurrentTraitsForeign>, - #[subdiagnostic] - name: Vec<OnlyCurrentTraitsName<'a>>, - #[subdiagnostic] - pointer: Vec<OnlyCurrentTraitsPointer<'a>>, - #[subdiagnostic] - ty: Vec<OnlyCurrentTraitsTy<'a>>, - #[subdiagnostic] - sugg: Option<OnlyCurrentTraitsPointerSugg<'a>>, }, } @@ -1445,7 +1409,6 @@ pub struct OnlyCurrentTraitsOpaque { #[primary_span] pub span: Span, } - #[derive(Subdiagnostic)] #[label(hir_analysis_only_current_traits_foreign)] pub struct OnlyCurrentTraitsForeign { @@ -1478,6 +1441,14 @@ pub struct OnlyCurrentTraitsTy<'a> { } #[derive(Subdiagnostic)] +#[label(hir_analysis_only_current_traits_adt)] +pub struct OnlyCurrentTraitsAdt { + #[primary_span] + pub span: Span, + pub name: String, +} + +#[derive(Subdiagnostic)] #[multipart_suggestion( hir_analysis_only_current_traits_pointer_sugg, applicability = "maybe-incorrect" diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index ebc5e11a561..8ea1a88be5d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1916,18 +1916,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat: &'tcx hir::Pat<'tcx>, ty: Ty<'tcx>, ) { - struct V<'tcx> { - tcx: TyCtxt<'tcx>, + struct V { pat_hir_ids: Vec<hir::HirId>, } - impl<'tcx> Visitor<'tcx> for V<'tcx> { - type NestedFilter = rustc_middle::hir::nested_filter::All; - - fn nested_visit_map(&mut self) -> Self::Map { - self.tcx.hir() - } - + impl<'tcx> Visitor<'tcx> for V { fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) { self.pat_hir_ids.push(p.hir_id); hir::intravisit::walk_pat(self, p); @@ -1938,7 +1931,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let err = Ty::new_error(self.tcx, guar); self.write_ty(hir_id, err); self.write_ty(pat.hir_id, err); - let mut visitor = V { tcx: self.tcx, pat_hir_ids: vec![] }; + let mut visitor = V { pat_hir_ids: vec![] }; hir::intravisit::walk_pat(&mut visitor, pat); // Mark all the subpatterns as `{type error}` as well. This allows errors for specific // subpatterns to be silenced. diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index cf3890dc61c..a034bebc85e 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1632,11 +1632,13 @@ pub struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> { pub ne: &'a str, pub deref_left: &'a str, pub deref_right: &'a str, + pub l_modifiers: &'a str, + pub r_modifiers: &'a str, #[suggestion_part(code = "{ne}std::ptr::eq({deref_left}")] pub left: Span, - #[suggestion_part(code = ", {deref_right}")] + #[suggestion_part(code = "{l_modifiers}, {deref_right}")] pub middle: Span, - #[suggestion_part(code = ")")] + #[suggestion_part(code = "{r_modifiers})")] pub right: Span, } @@ -1652,11 +1654,13 @@ pub enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> { ne: &'a str, deref_left: &'a str, deref_right: &'a str, + l_modifiers: &'a str, + r_modifiers: &'a str, #[suggestion_part(code = "{ne}std::ptr::addr_eq({deref_left}")] left: Span, - #[suggestion_part(code = ", {deref_right}")] + #[suggestion_part(code = "{l_modifiers}, {deref_right}")] middle: Span, - #[suggestion_part(code = ")")] + #[suggestion_part(code = "{r_modifiers})")] right: Span, }, #[multipart_suggestion( @@ -1670,13 +1674,15 @@ pub enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> { deref_right: &'a str, paren_left: &'a str, paren_right: &'a str, + l_modifiers: &'a str, + r_modifiers: &'a str, #[suggestion_part(code = "({deref_left}")] left_before: Option<Span>, - #[suggestion_part(code = "{paren_left}.cast::<()>()")] + #[suggestion_part(code = "{l_modifiers}{paren_left}.cast::<()>()")] left_after: Span, #[suggestion_part(code = "({deref_right}")] right_before: Option<Span>, - #[suggestion_part(code = "{paren_right}.cast::<()>()")] + #[suggestion_part(code = "{r_modifiers}{paren_right}.cast::<()>()")] right_after: Span, }, } diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 68cc024d9c7..534eb60eeb0 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -670,7 +670,11 @@ fn lint_wide_pointer<'tcx>( l: &'tcx hir::Expr<'tcx>, r: &'tcx hir::Expr<'tcx>, ) { - let ptr_unsized = |mut ty: Ty<'tcx>| -> Option<(usize, bool)> { + let ptr_unsized = |mut ty: Ty<'tcx>| -> Option<( + /* number of refs */ usize, + /* modifiers */ String, + /* is dyn */ bool, + )> { let mut refs = 0; // here we remove any "implicit" references and count the number // of them to correctly suggest the right number of deref @@ -678,11 +682,20 @@ fn lint_wide_pointer<'tcx>( ty = *inner_ty; refs += 1; } - match ty.kind() { - ty::RawPtr(ty, _) => (!ty.is_sized(cx.tcx, cx.param_env)) - .then(|| (refs, matches!(ty.kind(), ty::Dynamic(_, _, ty::Dyn)))), - _ => None, - } + + // get the inner type of a pointer (or akin) + let mut modifiers = String::new(); + ty = match ty.kind() { + ty::RawPtr(ty, _) => *ty, + ty::Adt(def, args) if cx.tcx.is_diagnostic_item(sym::NonNull, def.did()) => { + modifiers.push_str(".as_ptr()"); + args.type_at(0) + } + _ => return None, + }; + + (!ty.is_sized(cx.tcx, cx.param_env)) + .then(|| (refs, modifiers, matches!(ty.kind(), ty::Dynamic(_, _, ty::Dyn)))) }; // the left and right operands can have references, remove any explicit references @@ -696,10 +709,10 @@ fn lint_wide_pointer<'tcx>( return; }; - let Some((l_ty_refs, l_inner_ty_is_dyn)) = ptr_unsized(l_ty) else { + let Some((l_ty_refs, l_modifiers, l_inner_ty_is_dyn)) = ptr_unsized(l_ty) else { return; }; - let Some((r_ty_refs, r_inner_ty_is_dyn)) = ptr_unsized(r_ty) else { + let Some((r_ty_refs, r_modifiers, r_inner_ty_is_dyn)) = ptr_unsized(r_ty) else { return; }; @@ -724,6 +737,9 @@ fn lint_wide_pointer<'tcx>( let deref_left = &*"*".repeat(l_ty_refs); let deref_right = &*"*".repeat(r_ty_refs); + let l_modifiers = &*l_modifiers; + let r_modifiers = &*r_modifiers; + cx.emit_span_lint( AMBIGUOUS_WIDE_POINTER_COMPARISONS, e.span, @@ -733,6 +749,8 @@ fn lint_wide_pointer<'tcx>( ne, deref_left, deref_right, + l_modifiers, + r_modifiers, left, middle, right, @@ -743,6 +761,8 @@ fn lint_wide_pointer<'tcx>( ne, deref_left, deref_right, + l_modifiers, + r_modifiers, left, middle, right, @@ -751,6 +771,8 @@ fn lint_wide_pointer<'tcx>( AmbiguousWidePointerComparisonsAddrSuggestion::Cast { deref_left, deref_right, + l_modifiers, + r_modifiers, paren_left: if l_ty_refs != 0 { ")" } else { "" }, paren_right: if r_ty_refs != 0 { ")" } else { "" }, left_before: (l_ty_refs != 0).then_some(l_span.shrink_to_lo()), diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs index 867faf63261..b92800a1728 100644 --- a/compiler/rustc_middle/src/ty/region.rs +++ b/compiler/rustc_middle/src/ty/region.rs @@ -140,6 +140,10 @@ impl<'tcx> rustc_type_ir::new::Region<TyCtxt<'tcx>> for Region<'tcx> { fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self { Region::new_bound(tcx, debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon }) } + + fn new_static(tcx: TyCtxt<'tcx>) -> Self { + tcx.lifetimes.re_static + } } /// Region utilities diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 57a675e4453..b5e619f1e2a 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1624,6 +1624,13 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_adt(tcx: TyCtxt<'tcx>, def: AdtDef<'tcx>, args: GenericArgsRef<'tcx>) -> Ty<'tcx> { + debug_assert_eq!( + tcx.generics_of(def.did()).count(), + args.len(), + "wrong number of args for ADT: {:#?} vs {:#?}", + tcx.generics_of(def.did()).params, + args + ); Ty::new(tcx, Adt(def, args)) } diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index b66dd83b7ec..690879b9488 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -650,12 +650,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - // FIXME(#29623): return `Some(1)` when the values are different. - (TestKind::Eq { value: test_val, .. }, TestCase::Constant { value: case_val }) - if test_val == case_val => - { - fully_matched = true; - Some(TestBranch::Success) + (TestKind::Eq { value: test_val, .. }, TestCase::Constant { value: case_val }) => { + if test_val == case_val { + fully_matched = true; + Some(TestBranch::Success) + } else { + fully_matched = false; + Some(TestBranch::Failure) + } } ( diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 16d8453ea24..1899517c0e2 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -296,10 +296,7 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I> Region::new_anon_bound(self.interner(), self.binder_index, var) } - fn fold_ty(&mut self, t: I::Ty) -> I::Ty - where - I::Ty: TypeSuperFoldable<I>, - { + fn fold_ty(&mut self, t: I::Ty) -> I::Ty { let kind = match t.kind() { ty::Infer(i) => match i { ty::TyVar(vid) => { @@ -378,47 +375,48 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I> Ty::new_anon_bound(self.interner(), self.binder_index, var) } - fn fold_const(&mut self, c: I::Const) -> I::Const - where - I::Const: TypeSuperFoldable<I>, - { + fn fold_const(&mut self, c: I::Const) -> I::Const { + // We could canonicalize all consts with static types, but the only ones we + // *really* need to worry about are the ones that we end up putting into `CanonicalVarKind` + // since canonical vars can't reference other canonical vars. + let ty = c + .ty() + .fold_with(&mut RegionsToStatic { interner: self.interner(), binder: ty::INNERMOST }); let kind = match c.kind() { - ty::ConstKind::Infer(i) => { - // FIXME: we should fold the ty too eventually - match i { - ty::InferConst::Var(vid) => { - assert_eq!( - self.infcx.root_ct_var(vid), - vid, - "region vid should have been resolved fully before canonicalization" - ); - assert_eq!( - self.infcx.probe_ct_var(vid), - None, - "region vid should have been resolved fully before canonicalization" - ); - CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap(), c.ty()) - } - ty::InferConst::EffectVar(_) => CanonicalVarKind::Effect, - ty::InferConst::Fresh(_) => todo!(), + ty::ConstKind::Infer(i) => match i { + ty::InferConst::Var(vid) => { + assert_eq!( + self.infcx.root_ct_var(vid), + vid, + "region vid should have been resolved fully before canonicalization" + ); + assert_eq!( + self.infcx.probe_ct_var(vid), + None, + "region vid should have been resolved fully before canonicalization" + ); + CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap(), ty) } - } + ty::InferConst::EffectVar(_) => CanonicalVarKind::Effect, + ty::InferConst::Fresh(_) => todo!(), + }, ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode { CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst( PlaceholderLike::new(placeholder.universe(), self.variables.len().into()), - c.ty(), + ty, ), CanonicalizeMode::Response { .. } => { - CanonicalVarKind::PlaceholderConst(placeholder, c.ty()) + CanonicalVarKind::PlaceholderConst(placeholder, ty) } }, ty::ConstKind::Param(_) => match self.canonicalize_mode { CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst( PlaceholderLike::new(ty::UniverseIndex::ROOT, self.variables.len().into()), - c.ty(), + ty, ), CanonicalizeMode::Response { .. } => panic!("param ty in response: {c:?}"), }, + // FIXME: See comment above -- we could fold the region separately or something. ty::ConstKind::Bound(_, _) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Value(_) @@ -435,6 +433,35 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I> }), ); - Const::new_anon_bound(self.interner(), self.binder_index, var, c.ty()) + Const::new_anon_bound(self.interner(), self.binder_index, var, ty) + } +} + +struct RegionsToStatic<I> { + interner: I, + binder: ty::DebruijnIndex, +} + +impl<I: Interner> TypeFolder<I> for RegionsToStatic<I> { + fn interner(&self) -> I { + self.interner + } + + fn fold_binder<T>(&mut self, t: I::Binder<T>) -> I::Binder<T> + where + T: TypeFoldable<I>, + I::Binder<T>: TypeSuperFoldable<I>, + { + self.binder.shift_in(1); + let t = t.fold_with(self); + self.binder.shift_out(1); + t + } + + fn fold_region(&mut self, r: I::Region) -> I::Region { + match r.kind() { + ty::ReBound(db, _) if self.binder > db => r, + _ => Region::new_static(self.interner()), + } } } diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index 179fd79bef7..b8dacc6968d 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -96,6 +96,8 @@ session_sanitizer_cfi_requires_lto = `-Zsanitizer=cfi` requires `-Clto` or `-Cli session_sanitizer_cfi_requires_single_codegen_unit = `-Zsanitizer=cfi` with `-Clto` requires `-Ccodegen-units=1` +session_sanitizer_kcfi_requires_panic_abort = `-Z sanitizer=kcfi` requires `-C panic=abort` + session_sanitizer_not_supported = {$us} sanitizer is not supported for this target session_sanitizers_not_supported = {$us} sanitizers are not supported for this target diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 0a855f87586..2e4c7d14ecd 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -146,6 +146,10 @@ pub(crate) struct SanitizerCfiGeneralizePointersRequiresCfi; pub(crate) struct SanitizerCfiNormalizeIntegersRequiresCfi; #[derive(Diagnostic)] +#[diag(session_sanitizer_kcfi_requires_panic_abort)] +pub(crate) struct SanitizerKcfiRequiresPanicAbort; + +#[derive(Diagnostic)] #[diag(session_split_lto_unit_requires_lto)] pub(crate) struct SplitLtoUnitRequiresLto; diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 85428303382..55fff4421ae 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1211,6 +1211,11 @@ fn validate_commandline_args_with_session_available(sess: &Session) { sess.dcx().emit_err(errors::SanitizerCfiRequiresLto); } + // KCFI requires panic=abort + if sess.is_sanitizer_kcfi_enabled() && sess.panic_strategy() != PanicStrategy::Abort { + sess.dcx().emit_err(errors::SanitizerKcfiRequiresPanicAbort); + } + // LLVM CFI using rustc LTO requires a single codegen unit. if sess.is_sanitizer_cfi_enabled() && sess.lto() == config::Lto::Fat diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 7fd5cfeb48b..5963bd7c5f1 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -10,6 +10,7 @@ use rustc_data_structures::base_n; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; +use rustc_hir::lang_items::LangItem; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::{ @@ -641,9 +642,7 @@ fn encode_ty<'tcx>( } // Function types - ty::FnDef(def_id, args) - | ty::Closure(def_id, args) - | ty::CoroutineClosure(def_id, args) => { + ty::FnDef(def_id, args) | ty::Closure(def_id, args) => { // u<length><name>[I<element-type1..element-typeN>E], where <element-type> is <subst>, // as vendor extended type. let mut s = String::new(); @@ -654,6 +653,18 @@ fn encode_ty<'tcx>( typeid.push_str(&s); } + ty::CoroutineClosure(def_id, args) => { + // u<length><name>[I<element-type1..element-typeN>E], where <element-type> is <subst>, + // as vendor extended type. + let mut s = String::new(); + let name = encode_ty_name(tcx, *def_id); + let _ = write!(s, "u{}{}", name.len(), &name); + let parent_args = tcx.mk_args(args.as_coroutine_closure().parent_args()); + s.push_str(&encode_args(tcx, parent_args, dict, options)); + compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); + typeid.push_str(&s); + } + ty::Coroutine(def_id, args, ..) => { // u<length><name>[I<element-type1..element-typeN>E], where <element-type> is <subst>, // as vendor extended type. @@ -1140,45 +1151,102 @@ pub fn typeid_for_instance<'tcx>( 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); instance.args = tcx.mk_args_trait(self_ty, List::empty()); - } else if matches!(instance.def, ty::InstanceDef::Virtual(..)) { - instance.args = strip_receiver_auto(tcx, instance.args); + } else if let ty::InstanceDef::Virtual(def_id, _) = instance.def { + let upcast_ty = match tcx.trait_of_item(def_id) { + Some(trait_id) => trait_object_ty( + tcx, + ty::Binder::dummy(ty::TraitRef::from_method(tcx, trait_id, instance.args)), + ), + // drop_in_place won't have a defining trait, skip the upcast + None => instance.args.type_at(0), + }; + let stripped_ty = strip_receiver_auto(tcx, upcast_ty); + instance.args = tcx.mk_args_trait(stripped_ty, instance.args.into_iter().skip(1)); + } else if let ty::InstanceDef::VTableShim(def_id) = instance.def + && let Some(trait_id) = tcx.trait_of_item(def_id) + { + // VTableShims may have a trait method, but a concrete Self. This is not suitable for a vtable, + // as the caller will not know the concrete Self. + let trait_ref = ty::TraitRef::new(tcx, trait_id, instance.args); + let invoke_ty = trait_object_ty(tcx, ty::Binder::dummy(trait_ref)); + instance.args = tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1)); } - if !options.contains(EncodeTyOptions::NO_SELF_TYPE_ERASURE) - && let Some(impl_id) = tcx.impl_of_method(instance.def_id()) - && let Some(trait_ref) = tcx.impl_trait_ref(impl_id) - { - let impl_method = tcx.associated_item(instance.def_id()); - let method_id = impl_method - .trait_item_def_id - .expect("Part of a trait implementation, but not linked to the def_id?"); - let trait_method = tcx.associated_item(method_id); - let trait_id = trait_ref.skip_binder().def_id; - if traits::is_vtable_safe_method(tcx, trait_id, trait_method) - && tcx.object_safety_violations(trait_id).is_empty() + if !options.contains(EncodeTyOptions::NO_SELF_TYPE_ERASURE) { + if let Some(impl_id) = tcx.impl_of_method(instance.def_id()) + && let Some(trait_ref) = tcx.impl_trait_ref(impl_id) { - // Trait methods will have a Self polymorphic parameter, where the concreteized - // implementatation will not. We need to walk back to the more general trait method - let trait_ref = tcx.instantiate_and_normalize_erasing_regions( - instance.args, - ty::ParamEnv::reveal_all(), - trait_ref, - ); + let impl_method = tcx.associated_item(instance.def_id()); + let method_id = impl_method + .trait_item_def_id + .expect("Part of a trait implementation, but not linked to the def_id?"); + let trait_method = tcx.associated_item(method_id); + let trait_id = trait_ref.skip_binder().def_id; + if traits::is_vtable_safe_method(tcx, trait_id, trait_method) + && tcx.object_safety_violations(trait_id).is_empty() + { + // Trait methods will have a Self polymorphic parameter, where the concreteized + // implementatation will not. We need to walk back to the more general trait method + let trait_ref = tcx.instantiate_and_normalize_erasing_regions( + instance.args, + ty::ParamEnv::reveal_all(), + trait_ref, + ); + let invoke_ty = trait_object_ty(tcx, ty::Binder::dummy(trait_ref)); + + // At the call site, any call to this concrete function through a vtable will be + // `Virtual(method_id, idx)` with appropriate arguments for the method. Since we have the + // original method id, and we've recovered the trait arguments, we can make the callee + // instance we're computing the alias set for match the caller instance. + // + // Right now, our code ignores the vtable index everywhere, so we use 0 as a placeholder. + // If we ever *do* start encoding the vtable index, we will need to generate an alias set + // based on which vtables we are putting this method into, as there will be more than one + // index value when supertraits are involved. + instance.def = ty::InstanceDef::Virtual(method_id, 0); + let abstract_trait_args = + tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1)); + instance.args = instance.args.rebase_onto(tcx, impl_id, abstract_trait_args); + } + } else if tcx.is_closure_like(instance.def_id()) { + // We're either a closure or a coroutine. Our goal is to find the trait we're defined on, + // instantiate it, and take the type of its only method as our own. + let closure_ty = instance.ty(tcx, ty::ParamEnv::reveal_all()); + let (trait_id, inputs) = match closure_ty.kind() { + ty::Closure(..) => { + let closure_args = instance.args.as_closure(); + let trait_id = tcx.fn_trait_kind_to_def_id(closure_args.kind()).unwrap(); + let tuple_args = + tcx.instantiate_bound_regions_with_erased(closure_args.sig()).inputs()[0]; + (trait_id, tuple_args) + } + ty::Coroutine(..) => ( + tcx.require_lang_item(LangItem::Coroutine, None), + instance.args.as_coroutine().resume_ty(), + ), + ty::CoroutineClosure(..) => ( + tcx.require_lang_item(LangItem::FnOnce, None), + tcx.instantiate_bound_regions_with_erased( + instance.args.as_coroutine_closure().coroutine_closure_sig(), + ) + .tupled_inputs_ty, + ), + x => bug!("Unexpected type kind for closure-like: {x:?}"), + }; + let trait_ref = ty::TraitRef::new(tcx, trait_id, [closure_ty, inputs]); let invoke_ty = trait_object_ty(tcx, ty::Binder::dummy(trait_ref)); + let abstract_args = tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1)); + // There should be exactly one method on this trait, and it should be the one we're + // defining. + let call = tcx + .associated_items(trait_id) + .in_definition_order() + .find(|it| it.kind == ty::AssocKind::Fn) + .expect("No call-family function on closure-like Fn trait?") + .def_id; - // At the call site, any call to this concrete function through a vtable will be - // `Virtual(method_id, idx)` with appropriate arguments for the method. Since we have the - // original method id, and we've recovered the trait arguments, we can make the callee - // instance we're computing the alias set for match the caller instance. - // - // Right now, our code ignores the vtable index everywhere, so we use 0 as a placeholder. - // If we ever *do* start encoding the vtable index, we will need to generate an alias set - // based on which vtables we are putting this method into, as there will be more than one - // index value when supertraits are involved. - instance.def = ty::InstanceDef::Virtual(method_id, 0); - let abstract_trait_args = - tcx.mk_args_trait(invoke_ty, trait_ref.args.into_iter().skip(1)); - instance.args = instance.args.rebase_onto(tcx, impl_id, abstract_trait_args); + instance.def = ty::InstanceDef::Virtual(call, 0); + instance.args = abstract_args; } } @@ -1191,15 +1259,11 @@ pub fn typeid_for_instance<'tcx>( typeid_for_fnabi(tcx, fn_abi, options) } -fn strip_receiver_auto<'tcx>( - tcx: TyCtxt<'tcx>, - args: ty::GenericArgsRef<'tcx>, -) -> ty::GenericArgsRef<'tcx> { - let ty = args.type_at(0); +fn strip_receiver_auto<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { let ty::Dynamic(preds, lifetime, kind) = ty.kind() else { bug!("Tried to strip auto traits from non-dynamic type {ty}"); }; - let new_rcvr = if preds.principal().is_some() { + if preds.principal().is_some() { let filtered_preds = tcx.mk_poly_existential_predicates_from_iter(preds.into_iter().filter(|pred| { !matches!(pred.skip_binder(), ty::ExistentialPredicate::AutoTrait(..)) @@ -1210,8 +1274,7 @@ fn strip_receiver_auto<'tcx>( // about it. This technically discards the knowledge that it was a type that was made // into a trait object at some point, but that's not a lot. tcx.types.unit - }; - tcx.mk_args_trait(new_rcvr, args.into_iter().skip(1)) + } } #[instrument(skip(tcx), ret)] diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index 8d402588398..01bb3d73dbd 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -136,31 +136,21 @@ pub trait TypeFolder<I: Interner>: FallibleTypeFolder<I, Error = Never> { t.super_fold_with(self) } - fn fold_ty(&mut self, t: I::Ty) -> I::Ty - where - I::Ty: TypeSuperFoldable<I>, - { + fn fold_ty(&mut self, t: I::Ty) -> I::Ty { t.super_fold_with(self) } // The default region folder is a no-op because `Region` is non-recursive - // and has no `super_fold_with` method to call. That also explains the - // lack of `I::Region: TypeSuperFoldable<I>` bound on this method. + // and has no `super_fold_with` method to call. fn fold_region(&mut self, r: I::Region) -> I::Region { r } - fn fold_const(&mut self, c: I::Const) -> I::Const - where - I::Const: TypeSuperFoldable<I>, - { + fn fold_const(&mut self, c: I::Const) -> I::Const { c.super_fold_with(self) } - fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate - where - I::Predicate: TypeSuperFoldable<I>, - { + fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate { p.super_fold_with(self) } } @@ -185,31 +175,21 @@ pub trait FallibleTypeFolder<I: Interner>: Sized { t.try_super_fold_with(self) } - fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Self::Error> - where - I::Ty: TypeSuperFoldable<I>, - { + fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Self::Error> { t.try_super_fold_with(self) } // The default region folder is a no-op because `Region` is non-recursive - // and has no `super_fold_with` method to call. That also explains the - // lack of `I::Region: TypeSuperFoldable<I>` bound on this method. + // and has no `super_fold_with` method to call. fn try_fold_region(&mut self, r: I::Region) -> Result<I::Region, Self::Error> { Ok(r) } - fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Self::Error> - where - I::Const: TypeSuperFoldable<I>, - { + fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Self::Error> { c.try_super_fold_with(self) } - fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Self::Error> - where - I::Predicate: TypeSuperFoldable<I>, - { + fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Self::Error> { p.try_super_fold_with(self) } } @@ -234,10 +214,7 @@ where Ok(self.fold_binder(t)) } - fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Never> - where - I::Ty: TypeSuperFoldable<I>, - { + fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Never> { Ok(self.fold_ty(t)) } @@ -245,17 +222,11 @@ where Ok(self.fold_region(r)) } - fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Never> - where - I::Const: TypeSuperFoldable<I>, - { + fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Never> { Ok(self.fold_const(c)) } - fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Never> - where - I::Predicate: TypeSuperFoldable<I>, - { + fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Never> { Ok(self.fold_predicate(p)) } } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index ae1e1902f14..7a2885dd3bb 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -2,13 +2,14 @@ use smallvec::SmallVec; use std::fmt::Debug; use std::hash::Hash; +use crate::fold::TypeSuperFoldable; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; use crate::{ new, BoundVar, BoundVars, CanonicalVarInfo, ConstKind, DebugWithInfcx, RegionKind, TyKind, UniverseIndex, }; -pub trait Interner: Sized { +pub trait Interner: Sized + Copy { type DefId: Copy + Debug + Hash + Eq; type AdtDef: Copy + Debug + Hash + Eq; @@ -34,6 +35,7 @@ pub trait Interner: Sized { + Into<Self::GenericArg> + IntoKind<Kind = TyKind<Self>> + TypeSuperVisitable<Self> + + TypeSuperFoldable<Self> + Flags + new::Ty<Self>; type Tys: Copy + Debug + Hash + Eq + IntoIterator<Item = Self::Ty>; @@ -57,6 +59,7 @@ pub trait Interner: Sized { + IntoKind<Kind = ConstKind<Self>> + ConstTy<Self> + TypeSuperVisitable<Self> + + TypeSuperFoldable<Self> + Flags + new::Const<Self>; type AliasConst: Copy + DebugWithInfcx<Self> + Hash + Eq; @@ -82,7 +85,13 @@ pub trait Interner: Sized { type PlaceholderRegion: Copy + Debug + Hash + Eq + PlaceholderLike; // Predicates - type Predicate: Copy + Debug + Hash + Eq + TypeSuperVisitable<Self> + Flags; + type Predicate: Copy + + Debug + + Hash + + Eq + + TypeSuperVisitable<Self> + + TypeSuperFoldable<Self> + + Flags; type TraitPredicate: Copy + Debug + Hash + Eq; type RegionOutlivesPredicate: Copy + Debug + Hash + Eq; type TypeOutlivesPredicate: Copy + Debug + Hash + Eq; diff --git a/compiler/rustc_type_ir/src/new.rs b/compiler/rustc_type_ir/src/new.rs index e7e695e5908..1572a641d06 100644 --- a/compiler/rustc_type_ir/src/new.rs +++ b/compiler/rustc_type_ir/src/new.rs @@ -6,6 +6,8 @@ pub trait Ty<I: Interner<Ty = Self>> { pub trait Region<I: Interner<Region = Self>> { fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self; + + fn new_static(interner: I) -> Self; } pub trait Const<I: Interner<Const = Self>> { |
