| author | bors <bors@rust-lang.org> 2024-07-16 16:14:47 UTC |
| committer | bors <bors@rust-lang.org> 2024-07-16 16:14:47 UTC |
| log | 16b569057e4d1591b4bee05f10df34000308dedc |
| tree | 91e0788419dd4b30c1b21dfce0c11503c0d88ac4 |
| parent | a91f7d72f12efcc00ecf71591f066c534d45ddf7 |
| parent | ab4cc440dd4711fbdba04417aa43910d95576c13 |
Rollup of 8 pull requests
Successful merges:
- #127669 (Fix the issue of invalid suggestion for a reference of iterator)
- #127707 (match lowering: Use an iterator to find `expand_until`)
- #127730 (Fix and enforce `unsafe_op_in_unsafe_fn` in compiler)
- #127789 (delete #![allow(unsafe_op_in_unsafe_fn)] in teeos)
- #127805 (run-make-support: update gimli to 0.31.0)
- #127808 (Make ErrorGuaranteed discoverable outside types, consts, and lifetimes)
- #127817 (Fix a bunch of sites that were walking instead of visiting, making it impossible for visitor impls to look at these values)
- #127818 (Various ast validation simplifications)
r? `@ghost`
`@rustbot` modify labels: rollup30 files changed, 643 insertions(+), 500 deletions(-)
Cargo.lock+12-1| ... | ... | @@ -1618,6 +1618,17 @@ dependencies = [ |
| 1618 | 1618 | "rustc-std-workspace-core", |
| 1619 | 1619 | ] |
| 1620 | 1620 | |
| 1621 | [[package]] | |
| 1622 | name = "gimli" | |
| 1623 | version = "0.31.0" | |
| 1624 | source = "registry+https://github.com/rust-lang/crates.io-index" | |
| 1625 | checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" | |
| 1626 | dependencies = [ | |
| 1627 | "fallible-iterator", | |
| 1628 | "indexmap", | |
| 1629 | "stable_deref_trait", | |
| 1630 | ] | |
| 1631 | ||
| 1621 | 1632 | [[package]] |
| 1622 | 1633 | name = "glob" |
| 1623 | 1634 | version = "0.3.1" |
| ... | ... | @@ -3421,7 +3432,7 @@ dependencies = [ |
| 3421 | 3432 | "ar", |
| 3422 | 3433 | "bstr", |
| 3423 | 3434 | "build_helper", |
| 3424 | "gimli 0.28.1", | |
| 3435 | "gimli 0.31.0", | |
| 3425 | 3436 | "object 0.34.0", |
| 3426 | 3437 | "regex", |
| 3427 | 3438 | "similar", |
compiler/rustc_abi/src/lib.rs+2-2| ... | ... | @@ -627,7 +627,7 @@ impl Step for Size { |
| 627 | 627 | |
| 628 | 628 | #[inline] |
| 629 | 629 | unsafe fn forward_unchecked(start: Self, count: usize) -> Self { |
| 630 | Self::from_bytes(u64::forward_unchecked(start.bytes(), count)) | |
| 630 | Self::from_bytes(unsafe { u64::forward_unchecked(start.bytes(), count) }) | |
| 631 | 631 | } |
| 632 | 632 | |
| 633 | 633 | #[inline] |
| ... | ... | @@ -642,7 +642,7 @@ impl Step for Size { |
| 642 | 642 | |
| 643 | 643 | #[inline] |
| 644 | 644 | unsafe fn backward_unchecked(start: Self, count: usize) -> Self { |
| 645 | Self::from_bytes(u64::backward_unchecked(start.bytes(), count)) | |
| 645 | Self::from_bytes(unsafe { u64::backward_unchecked(start.bytes(), count) }) | |
| 646 | 646 | } |
| 647 | 647 | } |
| 648 | 648 |
compiler/rustc_ast/src/mut_visit.rs+3-3| ... | ... | @@ -482,7 +482,7 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) { |
| 482 | 482 | TyKind::Slice(ty) => vis.visit_ty(ty), |
| 483 | 483 | TyKind::Ptr(mt) => vis.visit_mt(mt), |
| 484 | 484 | TyKind::Ref(lt, mt) => { |
| 485 | visit_opt(lt, |lt| noop_visit_lifetime(lt, vis)); | |
| 485 | visit_opt(lt, |lt| vis.visit_lifetime(lt)); | |
| 486 | 486 | vis.visit_mt(mt); |
| 487 | 487 | } |
| 488 | 488 | TyKind::BareFn(bft) => { |
| ... | ... | @@ -925,7 +925,7 @@ pub fn noop_flat_map_generic_param<T: MutVisitor>( |
| 925 | 925 | vis.visit_id(id); |
| 926 | 926 | visit_attrs(attrs, vis); |
| 927 | 927 | vis.visit_ident(ident); |
| 928 | visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis)); | |
| 928 | visit_vec(bounds, |bound| vis.visit_param_bound(bound)); | |
| 929 | 929 | match kind { |
| 930 | 930 | GenericParamKind::Lifetime => {} |
| 931 | 931 | GenericParamKind::Type { default } => { |
| ... | ... | @@ -983,7 +983,7 @@ fn noop_visit_where_predicate<T: MutVisitor>(pred: &mut WherePredicate, vis: &mu |
| 983 | 983 | } |
| 984 | 984 | WherePredicate::RegionPredicate(rp) => { |
| 985 | 985 | let WhereRegionPredicate { span, lifetime, bounds } = rp; |
| 986 | noop_visit_lifetime(lifetime, vis); | |
| 986 | vis.visit_lifetime(lifetime); | |
| 987 | 987 | visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis)); |
| 988 | 988 | vis.visit_span(span); |
| 989 | 989 | } |
compiler/rustc_ast_passes/src/ast_validation.rs+26-70| ... | ... | @@ -38,7 +38,7 @@ use std::mem; |
| 38 | 38 | use std::ops::{Deref, DerefMut}; |
| 39 | 39 | use thin_vec::thin_vec; |
| 40 | 40 | |
| 41 | use crate::errors; | |
| 41 | use crate::errors::{self, TildeConstReason}; | |
| 42 | 42 | |
| 43 | 43 | /// Is `self` allowed semantically as the first parameter in an `FnDecl`? |
| 44 | 44 | enum SelfSemantic { |
| ... | ... | @@ -46,27 +46,12 @@ enum SelfSemantic { |
| 46 | 46 | No, |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | /// What is the context that prevents using `~const`? | |
| 50 | // FIXME(effects): Consider getting rid of this in favor of `errors::TildeConstReason`, they're | |
| 51 | // almost identical. This gets rid of an abstraction layer which might be considered bad. | |
| 52 | enum DisallowTildeConstContext<'a> { | |
| 53 | TraitObject, | |
| 54 | Fn(FnKind<'a>), | |
| 55 | Trait(Span), | |
| 56 | TraitImpl(Span), | |
| 57 | Impl(Span), | |
| 58 | TraitAssocTy(Span), | |
| 59 | TraitImplAssocTy(Span), | |
| 60 | InherentAssocTy(Span), | |
| 61 | Item, | |
| 62 | } | |
| 63 | ||
| 64 | enum TraitOrTraitImpl<'a> { | |
| 49 | enum TraitOrTraitImpl { | |
| 65 | 50 | Trait { span: Span, constness: Option<Span> }, |
| 66 | TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref: &'a TraitRef }, | |
| 51 | TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref: Span }, | |
| 67 | 52 | } |
| 68 | 53 | |
| 69 | impl<'a> TraitOrTraitImpl<'a> { | |
| 54 | impl TraitOrTraitImpl { | |
| 70 | 55 | fn constness(&self) -> Option<Span> { |
| 71 | 56 | match self { |
| 72 | 57 | Self::Trait { constness: Some(span), .. } |
| ... | ... | @@ -81,9 +66,9 @@ struct AstValidator<'a> { |
| 81 | 66 | features: &'a Features, |
| 82 | 67 | |
| 83 | 68 | /// The span of the `extern` in an `extern { ... }` block, if any. |
| 84 | extern_mod: Option<&'a Item>, | |
| 69 | extern_mod: Option<Span>, | |
| 85 | 70 | |
| 86 | outer_trait_or_trait_impl: Option<TraitOrTraitImpl<'a>>, | |
| 71 | outer_trait_or_trait_impl: Option<TraitOrTraitImpl>, | |
| 87 | 72 | |
| 88 | 73 | has_proc_macro_decls: bool, |
| 89 | 74 | |
| ... | ... | @@ -92,7 +77,7 @@ struct AstValidator<'a> { |
| 92 | 77 | /// e.g., `impl Iterator<Item = impl Debug>`. |
| 93 | 78 | outer_impl_trait: Option<Span>, |
| 94 | 79 | |
| 95 | disallow_tilde_const: Option<DisallowTildeConstContext<'a>>, | |
| 80 | disallow_tilde_const: Option<TildeConstReason>, | |
| 96 | 81 | |
| 97 | 82 | /// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item` |
| 98 | 83 | /// or `Foo::Bar<impl Trait>` |
| ... | ... | @@ -115,7 +100,7 @@ impl<'a> AstValidator<'a> { |
| 115 | 100 | trait_.map(|(constness, polarity, trait_ref)| TraitOrTraitImpl::TraitImpl { |
| 116 | 101 | constness, |
| 117 | 102 | polarity, |
| 118 | trait_ref, | |
| 103 | trait_ref: trait_ref.path.span, | |
| 119 | 104 | }), |
| 120 | 105 | ); |
| 121 | 106 | f(self); |
| ... | ... | @@ -145,7 +130,7 @@ impl<'a> AstValidator<'a> { |
| 145 | 130 | |
| 146 | 131 | fn with_tilde_const( |
| 147 | 132 | &mut self, |
| 148 | disallowed: Option<DisallowTildeConstContext<'a>>, | |
| 133 | disallowed: Option<TildeConstReason>, | |
| 149 | 134 | f: impl FnOnce(&mut Self), |
| 150 | 135 | ) { |
| 151 | 136 | let old = mem::replace(&mut self.disallow_tilde_const, disallowed); |
| ... | ... | @@ -224,7 +209,7 @@ impl<'a> AstValidator<'a> { |
| 224 | 209 | } |
| 225 | 210 | } |
| 226 | 211 | TyKind::TraitObject(..) => self |
| 227 | .with_tilde_const(Some(DisallowTildeConstContext::TraitObject), |this| { | |
| 212 | .with_tilde_const(Some(TildeConstReason::TraitObject), |this| { | |
| 228 | 213 | visit::walk_ty(this, t) |
| 229 | 214 | }), |
| 230 | 215 | TyKind::Path(qself, path) => { |
| ... | ... | @@ -354,7 +339,7 @@ impl<'a> AstValidator<'a> { |
| 354 | 339 | } |
| 355 | 340 | } |
| 356 | 341 | |
| 357 | fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl<'a>) { | |
| 342 | fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl) { | |
| 358 | 343 | let Const::Yes(span) = constness else { |
| 359 | 344 | return; |
| 360 | 345 | }; |
| ... | ... | @@ -367,7 +352,7 @@ impl<'a> AstValidator<'a> { |
| 367 | 352 | .. |
| 368 | 353 | } = parent |
| 369 | 354 | { |
| 370 | Some(trait_ref.path.span.shrink_to_lo()) | |
| 355 | Some(trait_ref.shrink_to_lo()) | |
| 371 | 356 | } else { |
| 372 | 357 | None |
| 373 | 358 | }; |
| ... | ... | @@ -579,7 +564,7 @@ impl<'a> AstValidator<'a> { |
| 579 | 564 | } |
| 580 | 565 | |
| 581 | 566 | fn current_extern_span(&self) -> Span { |
| 582 | self.session.source_map().guess_head_span(self.extern_mod.unwrap().span) | |
| 567 | self.session.source_map().guess_head_span(self.extern_mod.unwrap()) | |
| 583 | 568 | } |
| 584 | 569 | |
| 585 | 570 | /// An `fn` in `extern { ... }` cannot have qualifiers, e.g. `async fn`. |
| ... | ... | @@ -980,7 +965,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { |
| 980 | 965 | this.visit_vis(&item.vis); |
| 981 | 966 | this.visit_ident(item.ident); |
| 982 | 967 | let disallowed = matches!(constness, Const::No) |
| 983 | .then(|| DisallowTildeConstContext::TraitImpl(item.span)); | |
| 968 | .then(|| TildeConstReason::TraitImpl { span: item.span }); | |
| 984 | 969 | this.with_tilde_const(disallowed, |this| this.visit_generics(generics)); |
| 985 | 970 | this.visit_trait_ref(t); |
| 986 | 971 | this.visit_ty(self_ty); |
| ... | ... | @@ -1035,7 +1020,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { |
| 1035 | 1020 | this.visit_vis(&item.vis); |
| 1036 | 1021 | this.visit_ident(item.ident); |
| 1037 | 1022 | this.with_tilde_const( |
| 1038 | Some(DisallowTildeConstContext::Impl(item.span)), | |
| 1023 | Some(TildeConstReason::Impl { span: item.span }), | |
| 1039 | 1024 | |this| this.visit_generics(generics), |
| 1040 | 1025 | ); |
| 1041 | 1026 | this.visit_ty(self_ty); |
| ... | ... | @@ -1080,7 +1065,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { |
| 1080 | 1065 | } |
| 1081 | 1066 | ItemKind::ForeignMod(ForeignMod { abi, safety, .. }) => { |
| 1082 | 1067 | self.with_in_extern_mod(*safety, |this| { |
| 1083 | let old_item = mem::replace(&mut this.extern_mod, Some(item)); | |
| 1068 | let old_item = mem::replace(&mut this.extern_mod, Some(item.span)); | |
| 1084 | 1069 | this.visibility_not_permitted( |
| 1085 | 1070 | &item.vis, |
| 1086 | 1071 | errors::VisibilityNotPermittedNote::IndividualForeignItems, |
| ... | ... | @@ -1154,7 +1139,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { |
| 1154 | 1139 | this.visit_ident(item.ident); |
| 1155 | 1140 | let disallowed = is_const_trait |
| 1156 | 1141 | .is_none() |
| 1157 | .then(|| DisallowTildeConstContext::Trait(item.span)); | |
| 1142 | .then(|| TildeConstReason::Trait { span: item.span }); | |
| 1158 | 1143 | this.with_tilde_const(disallowed, |this| { |
| 1159 | 1144 | this.visit_generics(generics); |
| 1160 | 1145 | walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits) |
| ... | ... | @@ -1399,40 +1384,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { |
| 1399 | 1384 | self.dcx().emit_err(errors::ConstBoundTraitObject { span: trait_ref.span }); |
| 1400 | 1385 | } |
| 1401 | 1386 | (_, BoundConstness::Maybe(span), BoundPolarity::Positive) |
| 1402 | if let Some(reason) = &self.disallow_tilde_const => | |
| 1387 | if let Some(reason) = self.disallow_tilde_const => | |
| 1403 | 1388 | { |
| 1404 | let reason = match reason { | |
| 1405 | DisallowTildeConstContext::Fn(FnKind::Closure(..)) => { | |
| 1406 | errors::TildeConstReason::Closure | |
| 1407 | } | |
| 1408 | DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => { | |
| 1409 | errors::TildeConstReason::Function { ident: ident.span } | |
| 1410 | } | |
| 1411 | &DisallowTildeConstContext::Trait(span) => { | |
| 1412 | errors::TildeConstReason::Trait { span } | |
| 1413 | } | |
| 1414 | &DisallowTildeConstContext::TraitImpl(span) => { | |
| 1415 | errors::TildeConstReason::TraitImpl { span } | |
| 1416 | } | |
| 1417 | &DisallowTildeConstContext::Impl(span) => { | |
| 1418 | // FIXME(effects): Consider providing a help message or even a structured | |
| 1419 | // suggestion for moving such bounds to the assoc const fns if available. | |
| 1420 | errors::TildeConstReason::Impl { span } | |
| 1421 | } | |
| 1422 | &DisallowTildeConstContext::TraitAssocTy(span) => { | |
| 1423 | errors::TildeConstReason::TraitAssocTy { span } | |
| 1424 | } | |
| 1425 | &DisallowTildeConstContext::TraitImplAssocTy(span) => { | |
| 1426 | errors::TildeConstReason::TraitImplAssocTy { span } | |
| 1427 | } | |
| 1428 | &DisallowTildeConstContext::InherentAssocTy(span) => { | |
| 1429 | errors::TildeConstReason::InherentAssocTy { span } | |
| 1430 | } | |
| 1431 | DisallowTildeConstContext::TraitObject => { | |
| 1432 | errors::TildeConstReason::TraitObject | |
| 1433 | } | |
| 1434 | DisallowTildeConstContext::Item => errors::TildeConstReason::Item, | |
| 1435 | }; | |
| 1436 | 1389 | self.dcx().emit_err(errors::TildeConstDisallowed { span, reason }); |
| 1437 | 1390 | } |
| 1438 | 1391 | ( |
| ... | ... | @@ -1569,7 +1522,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { |
| 1569 | 1522 | .and_then(TraitOrTraitImpl::constness) |
| 1570 | 1523 | .is_some(); |
| 1571 | 1524 | |
| 1572 | let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk)); | |
| 1525 | let disallowed = (!tilde_const_allowed).then(|| match fk { | |
| 1526 | FnKind::Fn(_, ident, _, _, _, _) => TildeConstReason::Function { ident: ident.span }, | |
| 1527 | FnKind::Closure(_, _, _) => TildeConstReason::Closure, | |
| 1528 | }); | |
| 1573 | 1529 | self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk)); |
| 1574 | 1530 | } |
| 1575 | 1531 | |
| ... | ... | @@ -1664,12 +1620,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { |
| 1664 | 1620 | AssocItemKind::Type(_) => { |
| 1665 | 1621 | let disallowed = (!parent_is_const).then(|| match self.outer_trait_or_trait_impl { |
| 1666 | 1622 | Some(TraitOrTraitImpl::Trait { .. }) => { |
| 1667 | DisallowTildeConstContext::TraitAssocTy(item.span) | |
| 1623 | TildeConstReason::TraitAssocTy { span: item.span } | |
| 1668 | 1624 | } |
| 1669 | 1625 | Some(TraitOrTraitImpl::TraitImpl { .. }) => { |
| 1670 | DisallowTildeConstContext::TraitImplAssocTy(item.span) | |
| 1626 | TildeConstReason::TraitImplAssocTy { span: item.span } | |
| 1671 | 1627 | } |
| 1672 | None => DisallowTildeConstContext::InherentAssocTy(item.span), | |
| 1628 | None => TildeConstReason::InherentAssocTy { span: item.span }, | |
| 1673 | 1629 | }); |
| 1674 | 1630 | self.with_tilde_const(disallowed, |this| { |
| 1675 | 1631 | this.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)) |
| ... | ... | @@ -1852,7 +1808,7 @@ pub fn check_crate( |
| 1852 | 1808 | outer_trait_or_trait_impl: None, |
| 1853 | 1809 | has_proc_macro_decls: false, |
| 1854 | 1810 | outer_impl_trait: None, |
| 1855 | disallow_tilde_const: Some(DisallowTildeConstContext::Item), | |
| 1811 | disallow_tilde_const: Some(TildeConstReason::Item), | |
| 1856 | 1812 | is_impl_trait_banned: false, |
| 1857 | 1813 | extern_mod_safety: None, |
| 1858 | 1814 | lint_buffer: lints, |
compiler/rustc_ast_passes/src/errors.rs+1-1| ... | ... | @@ -612,7 +612,7 @@ pub struct TildeConstDisallowed { |
| 612 | 612 | pub reason: TildeConstReason, |
| 613 | 613 | } |
| 614 | 614 | |
| 615 | #[derive(Subdiagnostic)] | |
| 615 | #[derive(Subdiagnostic, Copy, Clone)] | |
| 616 | 616 | pub enum TildeConstReason { |
| 617 | 617 | #[note(ast_passes_closure)] |
| 618 | 618 | Closure, |
compiler/rustc_codegen_llvm/src/allocator.rs+27-23| ... | ... | @@ -21,14 +21,16 @@ pub(crate) unsafe fn codegen( |
| 21 | 21 | ) { |
| 22 | 22 | let llcx = &*module_llvm.llcx; |
| 23 | 23 | let llmod = module_llvm.llmod(); |
| 24 | let usize = match tcx.sess.target.pointer_width { | |
| 25 | 16 => llvm::LLVMInt16TypeInContext(llcx), | |
| 26 | 32 => llvm::LLVMInt32TypeInContext(llcx), | |
| 27 | 64 => llvm::LLVMInt64TypeInContext(llcx), | |
| 28 | tws => bug!("Unsupported target word size for int: {}", tws), | |
| 24 | let usize = unsafe { | |
| 25 | match tcx.sess.target.pointer_width { | |
| 26 | 16 => llvm::LLVMInt16TypeInContext(llcx), | |
| 27 | 32 => llvm::LLVMInt32TypeInContext(llcx), | |
| 28 | 64 => llvm::LLVMInt64TypeInContext(llcx), | |
| 29 | tws => bug!("Unsupported target word size for int: {}", tws), | |
| 30 | } | |
| 29 | 31 | }; |
| 30 | let i8 = llvm::LLVMInt8TypeInContext(llcx); | |
| 31 | let i8p = llvm::LLVMPointerTypeInContext(llcx, 0); | |
| 32 | let i8 = unsafe { llvm::LLVMInt8TypeInContext(llcx) }; | |
| 33 | let i8p = unsafe { llvm::LLVMPointerTypeInContext(llcx, 0) }; | |
| 32 | 34 | |
| 33 | 35 | if kind == AllocatorKind::Default { |
| 34 | 36 | for method in ALLOCATOR_METHODS { |
| ... | ... | @@ -73,23 +75,25 @@ pub(crate) unsafe fn codegen( |
| 73 | 75 | true, |
| 74 | 76 | ); |
| 75 | 77 | |
| 76 | // __rust_alloc_error_handler_should_panic | |
| 77 | let name = OomStrategy::SYMBOL; | |
| 78 | let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8); | |
| 79 | if tcx.sess.default_hidden_visibility() { | |
| 80 | llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden); | |
| 81 | } | |
| 82 | let val = tcx.sess.opts.unstable_opts.oom.should_panic(); | |
| 83 | let llval = llvm::LLVMConstInt(i8, val as u64, False); | |
| 84 | llvm::LLVMSetInitializer(ll_g, llval); | |
| 85 | ||
| 86 | let name = NO_ALLOC_SHIM_IS_UNSTABLE; | |
| 87 | let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8); | |
| 88 | if tcx.sess.default_hidden_visibility() { | |
| 89 | llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden); | |
| 78 | unsafe { | |
| 79 | // __rust_alloc_error_handler_should_panic | |
| 80 | let name = OomStrategy::SYMBOL; | |
| 81 | let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8); | |
| 82 | if tcx.sess.default_hidden_visibility() { | |
| 83 | llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden); | |
| 84 | } | |
| 85 | let val = tcx.sess.opts.unstable_opts.oom.should_panic(); | |
| 86 | let llval = llvm::LLVMConstInt(i8, val as u64, False); | |
| 87 | llvm::LLVMSetInitializer(ll_g, llval); | |
| 88 | ||
| 89 | let name = NO_ALLOC_SHIM_IS_UNSTABLE; | |
| 90 | let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8); | |
| 91 | if tcx.sess.default_hidden_visibility() { | |
| 92 | llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden); | |
| 93 | } | |
| 94 | let llval = llvm::LLVMConstInt(i8, 0, False); | |
| 95 | llvm::LLVMSetInitializer(ll_g, llval); | |
| 90 | 96 | } |
| 91 | let llval = llvm::LLVMConstInt(i8, 0, False); | |
| 92 | llvm::LLVMSetInitializer(ll_g, llval); | |
| 93 | 97 | |
| 94 | 98 | if tcx.sess.opts.debuginfo != DebugInfo::None { |
| 95 | 99 | let dbg_cx = debuginfo::CodegenUnitDebugContext::new(llmod); |
compiler/rustc_codegen_llvm/src/back/lto.rs+11-5| ... | ... | @@ -727,7 +727,7 @@ pub unsafe fn optimize_thin_module( |
| 727 | 727 | // into that context. One day, however, we may do this for upstream |
| 728 | 728 | // crates but for locally codegened modules we may be able to reuse |
| 729 | 729 | // that LLVM Context and Module. |
| 730 | let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names); | |
| 730 | let llcx = unsafe { llvm::LLVMRustContextCreate(cgcx.fewer_names) }; | |
| 731 | 731 | let llmod_raw = parse_module(llcx, module_name, thin_module.data(), dcx)? as *const _; |
| 732 | 732 | let mut module = ModuleCodegen { |
| 733 | 733 | module_llvm: ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) }, |
| ... | ... | @@ -750,7 +750,9 @@ pub unsafe fn optimize_thin_module( |
| 750 | 750 | { |
| 751 | 751 | let _timer = |
| 752 | 752 | cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_rename", thin_module.name()); |
| 753 | if !llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod, target) { | |
| 753 | if unsafe { | |
| 754 | !llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod, target) | |
| 755 | } { | |
| 754 | 756 | return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule)); |
| 755 | 757 | } |
| 756 | 758 | save_temp_bitcode(cgcx, &module, "thin-lto-after-rename"); |
| ... | ... | @@ -760,7 +762,8 @@ pub unsafe fn optimize_thin_module( |
| 760 | 762 | let _timer = cgcx |
| 761 | 763 | .prof |
| 762 | 764 | .generic_activity_with_arg("LLVM_thin_lto_resolve_weak", thin_module.name()); |
| 763 | if !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) { | |
| 765 | if unsafe { !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) } | |
| 766 | { | |
| 764 | 767 | return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule)); |
| 765 | 768 | } |
| 766 | 769 | save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve"); |
| ... | ... | @@ -770,7 +773,8 @@ pub unsafe fn optimize_thin_module( |
| 770 | 773 | let _timer = cgcx |
| 771 | 774 | .prof |
| 772 | 775 | .generic_activity_with_arg("LLVM_thin_lto_internalize", thin_module.name()); |
| 773 | if !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) { | |
| 776 | if unsafe { !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) } | |
| 777 | { | |
| 774 | 778 | return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule)); |
| 775 | 779 | } |
| 776 | 780 | save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize"); |
| ... | ... | @@ -779,7 +783,9 @@ pub unsafe fn optimize_thin_module( |
| 779 | 783 | { |
| 780 | 784 | let _timer = |
| 781 | 785 | cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_import", thin_module.name()); |
| 782 | if !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod, target) { | |
| 786 | if unsafe { | |
| 787 | !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod, target) | |
| 788 | } { | |
| 783 | 789 | return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule)); |
| 784 | 790 | } |
| 785 | 791 | save_temp_bitcode(cgcx, &module, "thin-lto-after-import"); |
compiler/rustc_codegen_llvm/src/back/profiling.rs+7-5| ... | ... | @@ -46,13 +46,15 @@ pub unsafe extern "C" fn selfprofile_before_pass_callback( |
| 46 | 46 | pass_name: *const c_char, |
| 47 | 47 | ir_name: *const c_char, |
| 48 | 48 | ) { |
| 49 | let llvm_self_profiler = &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>); | |
| 50 | let pass_name = CStr::from_ptr(pass_name).to_str().expect("valid UTF-8"); | |
| 51 | let ir_name = CStr::from_ptr(ir_name).to_str().expect("valid UTF-8"); | |
| 52 | llvm_self_profiler.before_pass_callback(pass_name, ir_name); | |
| 49 | unsafe { | |
| 50 | let llvm_self_profiler = &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>); | |
| 51 | let pass_name = CStr::from_ptr(pass_name).to_str().expect("valid UTF-8"); | |
| 52 | let ir_name = CStr::from_ptr(ir_name).to_str().expect("valid UTF-8"); | |
| 53 | llvm_self_profiler.before_pass_callback(pass_name, ir_name); | |
| 54 | } | |
| 53 | 55 | } |
| 54 | 56 | |
| 55 | 57 | pub unsafe extern "C" fn selfprofile_after_pass_callback(llvm_self_profiler: *mut c_void) { |
| 56 | let llvm_self_profiler = &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>); | |
| 58 | let llvm_self_profiler = unsafe { &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>) }; | |
| 57 | 59 | llvm_self_profiler.after_pass_callback(); |
| 58 | 60 | } |
compiler/rustc_codegen_llvm/src/back/write.rs+119-105| ... | ... | @@ -428,9 +428,10 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void |
| 428 | 428 | if user.is_null() { |
| 429 | 429 | return; |
| 430 | 430 | } |
| 431 | let (cgcx, dcx) = *(user as *const (&CodegenContext<LlvmCodegenBackend>, DiagCtxtHandle<'_>)); | |
| 431 | let (cgcx, dcx) = | |
| 432 | unsafe { *(user as *const (&CodegenContext<LlvmCodegenBackend>, DiagCtxtHandle<'_>)) }; | |
| 432 | 433 | |
| 433 | match llvm::diagnostic::Diagnostic::unpack(info) { | |
| 434 | match unsafe { llvm::diagnostic::Diagnostic::unpack(info) } { | |
| 434 | 435 | llvm::diagnostic::InlineAsm(inline) => { |
| 435 | 436 | report_inline_asm(cgcx, inline.message, inline.level, inline.cookie, inline.source); |
| 436 | 437 | } |
| ... | ... | @@ -454,14 +455,14 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void |
| 454 | 455 | }); |
| 455 | 456 | } |
| 456 | 457 | llvm::diagnostic::PGO(diagnostic_ref) | llvm::diagnostic::Linker(diagnostic_ref) => { |
| 457 | let message = llvm::build_string(|s| { | |
| 458 | let message = llvm::build_string(|s| unsafe { | |
| 458 | 459 | llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s) |
| 459 | 460 | }) |
| 460 | 461 | .expect("non-UTF8 diagnostic"); |
| 461 | 462 | dcx.emit_warn(FromLlvmDiag { message }); |
| 462 | 463 | } |
| 463 | 464 | llvm::diagnostic::Unsupported(diagnostic_ref) => { |
| 464 | let message = llvm::build_string(|s| { | |
| 465 | let message = llvm::build_string(|s| unsafe { | |
| 465 | 466 | llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s) |
| 466 | 467 | }) |
| 467 | 468 | .expect("non-UTF8 diagnostic"); |
| ... | ... | @@ -564,37 +565,39 @@ pub(crate) unsafe fn llvm_optimize( |
| 564 | 565 | |
| 565 | 566 | let llvm_plugins = config.llvm_plugins.join(","); |
| 566 | 567 | |
| 567 | let result = llvm::LLVMRustOptimize( | |
| 568 | module.module_llvm.llmod(), | |
| 569 | &*module.module_llvm.tm, | |
| 570 | to_pass_builder_opt_level(opt_level), | |
| 571 | opt_stage, | |
| 572 | cgcx.opts.cg.linker_plugin_lto.enabled(), | |
| 573 | config.no_prepopulate_passes, | |
| 574 | config.verify_llvm_ir, | |
| 575 | using_thin_buffers, | |
| 576 | config.merge_functions, | |
| 577 | unroll_loops, | |
| 578 | config.vectorize_slp, | |
| 579 | config.vectorize_loop, | |
| 580 | config.no_builtins, | |
| 581 | config.emit_lifetime_markers, | |
| 582 | sanitizer_options.as_ref(), | |
| 583 | pgo_gen_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), | |
| 584 | pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), | |
| 585 | config.instrument_coverage, | |
| 586 | instr_profile_output_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), | |
| 587 | config.instrument_gcov, | |
| 588 | pgo_sample_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), | |
| 589 | config.debug_info_for_profiling, | |
| 590 | llvm_selfprofiler, | |
| 591 | selfprofile_before_pass_callback, | |
| 592 | selfprofile_after_pass_callback, | |
| 593 | extra_passes.as_ptr().cast(), | |
| 594 | extra_passes.len(), | |
| 595 | llvm_plugins.as_ptr().cast(), | |
| 596 | llvm_plugins.len(), | |
| 597 | ); | |
| 568 | let result = unsafe { | |
| 569 | llvm::LLVMRustOptimize( | |
| 570 | module.module_llvm.llmod(), | |
| 571 | &*module.module_llvm.tm, | |
| 572 | to_pass_builder_opt_level(opt_level), | |
| 573 | opt_stage, | |
| 574 | cgcx.opts.cg.linker_plugin_lto.enabled(), | |
| 575 | config.no_prepopulate_passes, | |
| 576 | config.verify_llvm_ir, | |
| 577 | using_thin_buffers, | |
| 578 | config.merge_functions, | |
| 579 | unroll_loops, | |
| 580 | config.vectorize_slp, | |
| 581 | config.vectorize_loop, | |
| 582 | config.no_builtins, | |
| 583 | config.emit_lifetime_markers, | |
| 584 | sanitizer_options.as_ref(), | |
| 585 | pgo_gen_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), | |
| 586 | pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), | |
| 587 | config.instrument_coverage, | |
| 588 | instr_profile_output_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), | |
| 589 | config.instrument_gcov, | |
| 590 | pgo_sample_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), | |
| 591 | config.debug_info_for_profiling, | |
| 592 | llvm_selfprofiler, | |
| 593 | selfprofile_before_pass_callback, | |
| 594 | selfprofile_after_pass_callback, | |
| 595 | extra_passes.as_ptr().cast(), | |
| 596 | extra_passes.len(), | |
| 597 | llvm_plugins.as_ptr().cast(), | |
| 598 | llvm_plugins.len(), | |
| 599 | ) | |
| 600 | }; | |
| 598 | 601 | result.into_result().map_err(|()| llvm_err(dcx, LlvmError::RunLlvmPasses)) |
| 599 | 602 | } |
| 600 | 603 | |
| ... | ... | @@ -617,7 +620,7 @@ pub(crate) unsafe fn optimize( |
| 617 | 620 | if config.emit_no_opt_bc { |
| 618 | 621 | let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name); |
| 619 | 622 | let out = path_to_c_string(&out); |
| 620 | llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()); | |
| 623 | unsafe { llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()) }; | |
| 621 | 624 | } |
| 622 | 625 | |
| 623 | 626 | if let Some(opt_level) = config.opt_level { |
| ... | ... | @@ -627,7 +630,7 @@ pub(crate) unsafe fn optimize( |
| 627 | 630 | _ if cgcx.opts.cg.linker_plugin_lto.enabled() => llvm::OptStage::PreLinkThinLTO, |
| 628 | 631 | _ => llvm::OptStage::PreLinkNoLTO, |
| 629 | 632 | }; |
| 630 | return llvm_optimize(cgcx, dcx, module, config, opt_level, opt_stage); | |
| 633 | return unsafe { llvm_optimize(cgcx, dcx, module, config, opt_level, opt_stage) }; | |
| 631 | 634 | } |
| 632 | 635 | Ok(()) |
| 633 | 636 | } |
| ... | ... | @@ -692,10 +695,12 @@ pub(crate) unsafe fn codegen( |
| 692 | 695 | where |
| 693 | 696 | F: FnOnce(&'ll mut PassManager<'ll>) -> R, |
| 694 | 697 | { |
| 695 | let cpm = llvm::LLVMCreatePassManager(); | |
| 696 | llvm::LLVMAddAnalysisPasses(tm, cpm); | |
| 697 | llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins); | |
| 698 | f(cpm) | |
| 698 | unsafe { | |
| 699 | let cpm = llvm::LLVMCreatePassManager(); | |
| 700 | llvm::LLVMAddAnalysisPasses(tm, cpm); | |
| 701 | llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins); | |
| 702 | f(cpm) | |
| 703 | } | |
| 699 | 704 | } |
| 700 | 705 | |
| 701 | 706 | // Two things to note: |
| ... | ... | @@ -757,7 +762,9 @@ pub(crate) unsafe fn codegen( |
| 757 | 762 | let _timer = cgcx |
| 758 | 763 | .prof |
| 759 | 764 | .generic_activity_with_arg("LLVM_module_codegen_embed_bitcode", &*module.name); |
| 760 | embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data); | |
| 765 | unsafe { | |
| 766 | embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data); | |
| 767 | } | |
| 761 | 768 | } |
| 762 | 769 | } |
| 763 | 770 | |
| ... | ... | @@ -793,7 +800,8 @@ pub(crate) unsafe fn codegen( |
| 793 | 800 | cursor.position() as size_t |
| 794 | 801 | } |
| 795 | 802 | |
| 796 | let result = llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback); | |
| 803 | let result = | |
| 804 | unsafe { llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback) }; | |
| 797 | 805 | |
| 798 | 806 | if result == llvm::LLVMRustResult::Success { |
| 799 | 807 | record_artifact_size(&cgcx.prof, "llvm_ir", &out); |
| ... | ... | @@ -812,22 +820,24 @@ pub(crate) unsafe fn codegen( |
| 812 | 820 | // binaries. So we must clone the module to produce the asm output |
| 813 | 821 | // if we are also producing object code. |
| 814 | 822 | let llmod = if let EmitObj::ObjectCode(_) = config.emit_obj { |
| 815 | llvm::LLVMCloneModule(llmod) | |
| 823 | unsafe { llvm::LLVMCloneModule(llmod) } | |
| 816 | 824 | } else { |
| 817 | 825 | llmod |
| 818 | 826 | }; |
| 819 | with_codegen(tm, llmod, config.no_builtins, |cpm| { | |
| 820 | write_output_file( | |
| 821 | dcx, | |
| 822 | tm, | |
| 823 | cpm, | |
| 824 | llmod, | |
| 825 | &path, | |
| 826 | None, | |
| 827 | llvm::FileType::AssemblyFile, | |
| 828 | &cgcx.prof, | |
| 829 | ) | |
| 830 | })?; | |
| 827 | unsafe { | |
| 828 | with_codegen(tm, llmod, config.no_builtins, |cpm| { | |
| 829 | write_output_file( | |
| 830 | dcx, | |
| 831 | tm, | |
| 832 | cpm, | |
| 833 | llmod, | |
| 834 | &path, | |
| 835 | None, | |
| 836 | llvm::FileType::AssemblyFile, | |
| 837 | &cgcx.prof, | |
| 838 | ) | |
| 839 | })?; | |
| 840 | } | |
| 831 | 841 | } |
| 832 | 842 | |
| 833 | 843 | match config.emit_obj { |
| ... | ... | @@ -851,18 +861,20 @@ pub(crate) unsafe fn codegen( |
| 851 | 861 | (_, SplitDwarfKind::Split) => Some(dwo_out.as_path()), |
| 852 | 862 | }; |
| 853 | 863 | |
| 854 | with_codegen(tm, llmod, config.no_builtins, |cpm| { | |
| 855 | write_output_file( | |
| 856 | dcx, | |
| 857 | tm, | |
| 858 | cpm, | |
| 859 | llmod, | |
| 860 | &obj_out, | |
| 861 | dwo_out, | |
| 862 | llvm::FileType::ObjectFile, | |
| 863 | &cgcx.prof, | |
| 864 | ) | |
| 865 | })?; | |
| 864 | unsafe { | |
| 865 | with_codegen(tm, llmod, config.no_builtins, |cpm| { | |
| 866 | write_output_file( | |
| 867 | dcx, | |
| 868 | tm, | |
| 869 | cpm, | |
| 870 | llmod, | |
| 871 | &obj_out, | |
| 872 | dwo_out, | |
| 873 | llvm::FileType::ObjectFile, | |
| 874 | &cgcx.prof, | |
| 875 | ) | |
| 876 | })?; | |
| 877 | } | |
| 866 | 878 | } |
| 867 | 879 | |
| 868 | 880 | EmitObj::Bitcode => { |
| ... | ... | @@ -1013,44 +1025,46 @@ unsafe fn embed_bitcode( |
| 1013 | 1025 | // reason (see issue #90326 for historical background). |
| 1014 | 1026 | let is_aix = target_is_aix(cgcx); |
| 1015 | 1027 | let is_apple = target_is_apple(cgcx); |
| 1016 | if is_apple || is_aix || cgcx.opts.target_triple.triple().starts_with("wasm") { | |
| 1017 | // We don't need custom section flags, create LLVM globals. | |
| 1018 | let llconst = common::bytes_in_context(llcx, bitcode); | |
| 1019 | let llglobal = llvm::LLVMAddGlobal( | |
| 1020 | llmod, | |
| 1021 | common::val_ty(llconst), | |
| 1022 | c"rustc.embedded.module".as_ptr().cast(), | |
| 1023 | ); | |
| 1024 | llvm::LLVMSetInitializer(llglobal, llconst); | |
| 1025 | ||
| 1026 | let section = bitcode_section_name(cgcx); | |
| 1027 | llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); | |
| 1028 | llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); | |
| 1029 | llvm::LLVMSetGlobalConstant(llglobal, llvm::True); | |
| 1030 | ||
| 1031 | let llconst = common::bytes_in_context(llcx, cmdline.as_bytes()); | |
| 1032 | let llglobal = llvm::LLVMAddGlobal( | |
| 1033 | llmod, | |
| 1034 | common::val_ty(llconst), | |
| 1035 | c"rustc.embedded.cmdline".as_ptr().cast(), | |
| 1036 | ); | |
| 1037 | llvm::LLVMSetInitializer(llglobal, llconst); | |
| 1038 | let section = if is_apple { | |
| 1039 | c"__LLVM,__cmdline" | |
| 1040 | } else if is_aix { | |
| 1041 | c".info" | |
| 1028 | unsafe { | |
| 1029 | if is_apple || is_aix || cgcx.opts.target_triple.triple().starts_with("wasm") { | |
| 1030 | // We don't need custom section flags, create LLVM globals. | |
| 1031 | let llconst = common::bytes_in_context(llcx, bitcode); | |
| 1032 | let llglobal = llvm::LLVMAddGlobal( | |
| 1033 | llmod, | |
| 1034 | common::val_ty(llconst), | |
| 1035 | c"rustc.embedded.module".as_ptr().cast(), | |
| 1036 | ); | |
| 1037 | llvm::LLVMSetInitializer(llglobal, llconst); | |
| 1038 | ||
| 1039 | let section = bitcode_section_name(cgcx); | |
| 1040 | llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); | |
| 1041 | llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); | |
| 1042 | llvm::LLVMSetGlobalConstant(llglobal, llvm::True); | |
| 1043 | ||
| 1044 | let llconst = common::bytes_in_context(llcx, cmdline.as_bytes()); | |
| 1045 | let llglobal = llvm::LLVMAddGlobal( | |
| 1046 | llmod, | |
| 1047 | common::val_ty(llconst), | |
| 1048 | c"rustc.embedded.cmdline".as_ptr().cast(), | |
| 1049 | ); | |
| 1050 | llvm::LLVMSetInitializer(llglobal, llconst); | |
| 1051 | let section = if is_apple { | |
| 1052 | c"__LLVM,__cmdline" | |
| 1053 | } else if is_aix { | |
| 1054 | c".info" | |
| 1055 | } else { | |
| 1056 | c".llvmcmd" | |
| 1057 | }; | |
| 1058 | llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); | |
| 1059 | llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); | |
| 1042 | 1060 | } else { |
| 1043 | c".llvmcmd" | |
| 1044 | }; | |
| 1045 | llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); | |
| 1046 | llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); | |
| 1047 | } else { | |
| 1048 | // We need custom section flags, so emit module-level inline assembly. | |
| 1049 | let section_flags = if cgcx.is_pe_coff { "n" } else { "e" }; | |
| 1050 | let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode); | |
| 1051 | llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); | |
| 1052 | let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes()); | |
| 1053 | llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); | |
| 1061 | // We need custom section flags, so emit module-level inline assembly. | |
| 1062 | let section_flags = if cgcx.is_pe_coff { "n" } else { "e" }; | |
| 1063 | let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode); | |
| 1064 | llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); | |
| 1065 | let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes()); | |
| 1066 | llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len()); | |
| 1067 | } | |
| 1054 | 1068 | } |
| 1055 | 1069 | } |
| 1056 | 1070 |
compiler/rustc_codegen_llvm/src/context.rs+149-110| ... | ... | @@ -120,7 +120,7 @@ pub unsafe fn create_module<'ll>( |
| 120 | 120 | ) -> &'ll llvm::Module { |
| 121 | 121 | let sess = tcx.sess; |
| 122 | 122 | let mod_name = SmallCStr::new(mod_name); |
| 123 | let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx); | |
| 123 | let llmod = unsafe { llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx) }; | |
| 124 | 124 | |
| 125 | 125 | let mut target_data_layout = sess.target.data_layout.to_string(); |
| 126 | 126 | let llvm_version = llvm_util::get_version(); |
| ... | ... | @@ -153,11 +153,14 @@ pub unsafe fn create_module<'ll>( |
| 153 | 153 | // Ensure the data-layout values hardcoded remain the defaults. |
| 154 | 154 | { |
| 155 | 155 | let tm = crate::back::write::create_informational_target_machine(tcx.sess); |
| 156 | llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm); | |
| 156 | unsafe { | |
| 157 | llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm); | |
| 158 | } | |
| 157 | 159 | |
| 158 | let llvm_data_layout = llvm::LLVMGetDataLayoutStr(llmod); | |
| 159 | let llvm_data_layout = str::from_utf8(CStr::from_ptr(llvm_data_layout).to_bytes()) | |
| 160 | .expect("got a non-UTF8 data-layout from LLVM"); | |
| 160 | let llvm_data_layout = unsafe { llvm::LLVMGetDataLayoutStr(llmod) }; | |
| 161 | let llvm_data_layout = | |
| 162 | str::from_utf8(unsafe { CStr::from_ptr(llvm_data_layout) }.to_bytes()) | |
| 163 | .expect("got a non-UTF8 data-layout from LLVM"); | |
| 161 | 164 | |
| 162 | 165 | if target_data_layout != llvm_data_layout { |
| 163 | 166 | tcx.dcx().emit_err(crate::errors::MismatchedDataLayout { |
| ... | ... | @@ -170,20 +173,28 @@ pub unsafe fn create_module<'ll>( |
| 170 | 173 | } |
| 171 | 174 | |
| 172 | 175 | let data_layout = SmallCStr::new(&target_data_layout); |
| 173 | llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr()); | |
| 176 | unsafe { | |
| 177 | llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr()); | |
| 178 | } | |
| 174 | 179 | |
| 175 | 180 | let llvm_target = SmallCStr::new(&sess.target.llvm_target); |
| 176 | llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr()); | |
| 181 | unsafe { | |
| 182 | llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr()); | |
| 183 | } | |
| 177 | 184 | |
| 178 | 185 | let reloc_model = sess.relocation_model(); |
| 179 | 186 | if matches!(reloc_model, RelocModel::Pic | RelocModel::Pie) { |
| 180 | llvm::LLVMRustSetModulePICLevel(llmod); | |
| 187 | unsafe { | |
| 188 | llvm::LLVMRustSetModulePICLevel(llmod); | |
| 189 | } | |
| 181 | 190 | // PIE is potentially more effective than PIC, but can only be used in executables. |
| 182 | 191 | // If all our outputs are executables, then we can relax PIC to PIE. |
| 183 | 192 | if reloc_model == RelocModel::Pie |
| 184 | 193 | || tcx.crate_types().iter().all(|ty| *ty == CrateType::Executable) |
| 185 | 194 | { |
| 186 | llvm::LLVMRustSetModulePIELevel(llmod); | |
| 195 | unsafe { | |
| 196 | llvm::LLVMRustSetModulePIELevel(llmod); | |
| 197 | } | |
| 187 | 198 | } |
| 188 | 199 | } |
| 189 | 200 | |
| ... | ... | @@ -192,95 +203,109 @@ pub unsafe fn create_module<'ll>( |
| 192 | 203 | // longer jumps) if a larger code model is used with a smaller one. |
| 193 | 204 | // |
| 194 | 205 | // See https://reviews.llvm.org/D52322 and https://reviews.llvm.org/D52323. |
| 195 | llvm::LLVMRustSetModuleCodeModel(llmod, to_llvm_code_model(sess.code_model())); | |
| 206 | unsafe { | |
| 207 | llvm::LLVMRustSetModuleCodeModel(llmod, to_llvm_code_model(sess.code_model())); | |
| 208 | } | |
| 196 | 209 | |
| 197 | 210 | // If skipping the PLT is enabled, we need to add some module metadata |
| 198 | 211 | // to ensure intrinsic calls don't use it. |
| 199 | 212 | if !sess.needs_plt() { |
| 200 | 213 | let avoid_plt = c"RtLibUseGOT".as_ptr().cast(); |
| 201 | llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1); | |
| 214 | unsafe { | |
| 215 | llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1); | |
| 216 | } | |
| 202 | 217 | } |
| 203 | 218 | |
| 204 | 219 | // Enable canonical jump tables if CFI is enabled. (See https://reviews.llvm.org/D65629.) |
| 205 | 220 | if sess.is_sanitizer_cfi_canonical_jump_tables_enabled() && sess.is_sanitizer_cfi_enabled() { |
| 206 | 221 | let canonical_jump_tables = c"CFI Canonical Jump Tables".as_ptr().cast(); |
| 207 | llvm::LLVMRustAddModuleFlagU32( | |
| 208 | llmod, | |
| 209 | llvm::LLVMModFlagBehavior::Override, | |
| 210 | canonical_jump_tables, | |
| 211 | 1, | |
| 212 | ); | |
| 222 | unsafe { | |
| 223 | llvm::LLVMRustAddModuleFlagU32( | |
| 224 | llmod, | |
| 225 | llvm::LLVMModFlagBehavior::Override, | |
| 226 | canonical_jump_tables, | |
| 227 | 1, | |
| 228 | ); | |
| 229 | } | |
| 213 | 230 | } |
| 214 | 231 | |
| 215 | 232 | // Enable LTO unit splitting if specified or if CFI is enabled. (See https://reviews.llvm.org/D53891.) |
| 216 | 233 | if sess.is_split_lto_unit_enabled() || sess.is_sanitizer_cfi_enabled() { |
| 217 | 234 | let enable_split_lto_unit = c"EnableSplitLTOUnit".as_ptr().cast(); |
| 218 | llvm::LLVMRustAddModuleFlagU32( | |
| 219 | llmod, | |
| 220 | llvm::LLVMModFlagBehavior::Override, | |
| 221 | enable_split_lto_unit, | |
| 222 | 1, | |
| 223 | ); | |
| 235 | unsafe { | |
| 236 | llvm::LLVMRustAddModuleFlagU32( | |
| 237 | llmod, | |
| 238 | llvm::LLVMModFlagBehavior::Override, | |
| 239 | enable_split_lto_unit, | |
| 240 | 1, | |
| 241 | ); | |
| 242 | } | |
| 224 | 243 | } |
| 225 | 244 | |
| 226 | 245 | // Add "kcfi" module flag if KCFI is enabled. (See https://reviews.llvm.org/D119296.) |
| 227 | 246 | if sess.is_sanitizer_kcfi_enabled() { |
| 228 | 247 | let kcfi = c"kcfi".as_ptr().cast(); |
| 229 | llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1); | |
| 248 | unsafe { | |
| 249 | llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1); | |
| 250 | } | |
| 230 | 251 | } |
| 231 | 252 | |
| 232 | 253 | // Control Flow Guard is currently only supported by the MSVC linker on Windows. |
| 233 | 254 | if sess.target.is_like_msvc { |
| 234 | match sess.opts.cg.control_flow_guard { | |
| 235 | CFGuard::Disabled => {} | |
| 236 | CFGuard::NoChecks => { | |
| 237 | // Set `cfguard=1` module flag to emit metadata only. | |
| 238 | llvm::LLVMRustAddModuleFlagU32( | |
| 239 | llmod, | |
| 240 | llvm::LLVMModFlagBehavior::Warning, | |
| 241 | c"cfguard".as_ptr() as *const _, | |
| 242 | 1, | |
| 243 | ) | |
| 244 | } | |
| 245 | CFGuard::Checks => { | |
| 246 | // Set `cfguard=2` module flag to emit metadata and checks. | |
| 247 | llvm::LLVMRustAddModuleFlagU32( | |
| 248 | llmod, | |
| 249 | llvm::LLVMModFlagBehavior::Warning, | |
| 250 | c"cfguard".as_ptr() as *const _, | |
| 251 | 2, | |
| 252 | ) | |
| 255 | unsafe { | |
| 256 | match sess.opts.cg.control_flow_guard { | |
| 257 | CFGuard::Disabled => {} | |
| 258 | CFGuard::NoChecks => { | |
| 259 | // Set `cfguard=1` module flag to emit metadata only. | |
| 260 | llvm::LLVMRustAddModuleFlagU32( | |
| 261 | llmod, | |
| 262 | llvm::LLVMModFlagBehavior::Warning, | |
| 263 | c"cfguard".as_ptr() as *const _, | |
| 264 | 1, | |
| 265 | ) | |
| 266 | } | |
| 267 | CFGuard::Checks => { | |
| 268 | // Set `cfguard=2` module flag to emit metadata and checks. | |
| 269 | llvm::LLVMRustAddModuleFlagU32( | |
| 270 | llmod, | |
| 271 | llvm::LLVMModFlagBehavior::Warning, | |
| 272 | c"cfguard".as_ptr() as *const _, | |
| 273 | 2, | |
| 274 | ) | |
| 275 | } | |
| 253 | 276 | } |
| 254 | 277 | } |
| 255 | 278 | } |
| 256 | 279 | |
| 257 | 280 | if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection { |
| 258 | 281 | if sess.target.arch == "aarch64" { |
| 259 | llvm::LLVMRustAddModuleFlagU32( | |
| 260 | llmod, | |
| 261 | llvm::LLVMModFlagBehavior::Min, | |
| 262 | c"branch-target-enforcement".as_ptr().cast(), | |
| 263 | bti.into(), | |
| 264 | ); | |
| 265 | llvm::LLVMRustAddModuleFlagU32( | |
| 266 | llmod, | |
| 267 | llvm::LLVMModFlagBehavior::Min, | |
| 268 | c"sign-return-address".as_ptr().cast(), | |
| 269 | pac_ret.is_some().into(), | |
| 270 | ); | |
| 271 | let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A }); | |
| 272 | llvm::LLVMRustAddModuleFlagU32( | |
| 273 | llmod, | |
| 274 | llvm::LLVMModFlagBehavior::Min, | |
| 275 | c"sign-return-address-all".as_ptr().cast(), | |
| 276 | pac_opts.leaf.into(), | |
| 277 | ); | |
| 278 | llvm::LLVMRustAddModuleFlagU32( | |
| 279 | llmod, | |
| 280 | llvm::LLVMModFlagBehavior::Min, | |
| 281 | c"sign-return-address-with-bkey".as_ptr().cast(), | |
| 282 | u32::from(pac_opts.key == PAuthKey::B), | |
| 283 | ); | |
| 282 | unsafe { | |
| 283 | llvm::LLVMRustAddModuleFlagU32( | |
| 284 | llmod, | |
| 285 | llvm::LLVMModFlagBehavior::Min, | |
| 286 | c"branch-target-enforcement".as_ptr().cast(), | |
| 287 | bti.into(), | |
| 288 | ); | |
| 289 | llvm::LLVMRustAddModuleFlagU32( | |
| 290 | llmod, | |
| 291 | llvm::LLVMModFlagBehavior::Min, | |
| 292 | c"sign-return-address".as_ptr().cast(), | |
| 293 | pac_ret.is_some().into(), | |
| 294 | ); | |
| 295 | let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A }); | |
| 296 | llvm::LLVMRustAddModuleFlagU32( | |
| 297 | llmod, | |
| 298 | llvm::LLVMModFlagBehavior::Min, | |
| 299 | c"sign-return-address-all".as_ptr().cast(), | |
| 300 | pac_opts.leaf.into(), | |
| 301 | ); | |
| 302 | llvm::LLVMRustAddModuleFlagU32( | |
| 303 | llmod, | |
| 304 | llvm::LLVMModFlagBehavior::Min, | |
| 305 | c"sign-return-address-with-bkey".as_ptr().cast(), | |
| 306 | u32::from(pac_opts.key == PAuthKey::B), | |
| 307 | ); | |
| 308 | } | |
| 284 | 309 | } else { |
| 285 | 310 | bug!( |
| 286 | 311 | "branch-protection used on non-AArch64 target; \ |
| ... | ... | @@ -291,39 +316,47 @@ pub unsafe fn create_module<'ll>( |
| 291 | 316 | |
| 292 | 317 | // Pass on the control-flow protection flags to LLVM (equivalent to `-fcf-protection` in Clang). |
| 293 | 318 | if let CFProtection::Branch | CFProtection::Full = sess.opts.unstable_opts.cf_protection { |
| 294 | llvm::LLVMRustAddModuleFlagU32( | |
| 295 | llmod, | |
| 296 | llvm::LLVMModFlagBehavior::Override, | |
| 297 | c"cf-protection-branch".as_ptr().cast(), | |
| 298 | 1, | |
| 299 | ) | |
| 319 | unsafe { | |
| 320 | llvm::LLVMRustAddModuleFlagU32( | |
| 321 | llmod, | |
| 322 | llvm::LLVMModFlagBehavior::Override, | |
| 323 | c"cf-protection-branch".as_ptr().cast(), | |
| 324 | 1, | |
| 325 | ); | |
| 326 | } | |
| 300 | 327 | } |
| 301 | 328 | if let CFProtection::Return | CFProtection::Full = sess.opts.unstable_opts.cf_protection { |
| 302 | llvm::LLVMRustAddModuleFlagU32( | |
| 303 | llmod, | |
| 304 | llvm::LLVMModFlagBehavior::Override, | |
| 305 | c"cf-protection-return".as_ptr().cast(), | |
| 306 | 1, | |
| 307 | ) | |
| 329 | unsafe { | |
| 330 | llvm::LLVMRustAddModuleFlagU32( | |
| 331 | llmod, | |
| 332 | llvm::LLVMModFlagBehavior::Override, | |
| 333 | c"cf-protection-return".as_ptr().cast(), | |
| 334 | 1, | |
| 335 | ); | |
| 336 | } | |
| 308 | 337 | } |
| 309 | 338 | |
| 310 | 339 | if sess.opts.unstable_opts.virtual_function_elimination { |
| 311 | llvm::LLVMRustAddModuleFlagU32( | |
| 312 | llmod, | |
| 313 | llvm::LLVMModFlagBehavior::Error, | |
| 314 | c"Virtual Function Elim".as_ptr().cast(), | |
| 315 | 1, | |
| 316 | ); | |
| 340 | unsafe { | |
| 341 | llvm::LLVMRustAddModuleFlagU32( | |
| 342 | llmod, | |
| 343 | llvm::LLVMModFlagBehavior::Error, | |
| 344 | c"Virtual Function Elim".as_ptr().cast(), | |
| 345 | 1, | |
| 346 | ); | |
| 347 | } | |
| 317 | 348 | } |
| 318 | 349 | |
| 319 | 350 | // Set module flag to enable Windows EHCont Guard (/guard:ehcont). |
| 320 | 351 | if sess.opts.unstable_opts.ehcont_guard { |
| 321 | llvm::LLVMRustAddModuleFlagU32( | |
| 322 | llmod, | |
| 323 | llvm::LLVMModFlagBehavior::Warning, | |
| 324 | c"ehcontguard".as_ptr() as *const _, | |
| 325 | 1, | |
| 326 | ) | |
| 352 | unsafe { | |
| 353 | llvm::LLVMRustAddModuleFlagU32( | |
| 354 | llmod, | |
| 355 | llvm::LLVMModFlagBehavior::Warning, | |
| 356 | c"ehcontguard".as_ptr() as *const _, | |
| 357 | 1, | |
| 358 | ) | |
| 359 | } | |
| 327 | 360 | } |
| 328 | 361 | |
| 329 | 362 | // Insert `llvm.ident` metadata. |
| ... | ... | @@ -333,16 +366,20 @@ pub unsafe fn create_module<'ll>( |
| 333 | 366 | #[allow(clippy::option_env_unwrap)] |
| 334 | 367 | let rustc_producer = |
| 335 | 368 | format!("rustc version {}", option_env!("CFG_VERSION").expect("CFG_VERSION")); |
| 336 | let name_metadata = llvm::LLVMMDStringInContext( | |
| 337 | llcx, | |
| 338 | rustc_producer.as_ptr().cast(), | |
| 339 | rustc_producer.as_bytes().len() as c_uint, | |
| 340 | ); | |
| 341 | llvm::LLVMAddNamedMetadataOperand( | |
| 342 | llmod, | |
| 343 | c"llvm.ident".as_ptr(), | |
| 344 | llvm::LLVMMDNodeInContext(llcx, &name_metadata, 1), | |
| 345 | ); | |
| 369 | let name_metadata = unsafe { | |
| 370 | llvm::LLVMMDStringInContext( | |
| 371 | llcx, | |
| 372 | rustc_producer.as_ptr().cast(), | |
| 373 | rustc_producer.as_bytes().len() as c_uint, | |
| 374 | ) | |
| 375 | }; | |
| 376 | unsafe { | |
| 377 | llvm::LLVMAddNamedMetadataOperand( | |
| 378 | llmod, | |
| 379 | c"llvm.ident".as_ptr(), | |
| 380 | llvm::LLVMMDNodeInContext(llcx, &name_metadata, 1), | |
| 381 | ); | |
| 382 | } | |
| 346 | 383 | |
| 347 | 384 | // Emit RISC-V specific target-abi metadata |
| 348 | 385 | // to workaround lld as the LTO plugin not |
| ... | ... | @@ -351,13 +388,15 @@ pub unsafe fn create_module<'ll>( |
| 351 | 388 | // If llvm_abiname is empty, emit nothing. |
| 352 | 389 | let llvm_abiname = &sess.target.options.llvm_abiname; |
| 353 | 390 | if matches!(sess.target.arch.as_ref(), "riscv32" | "riscv64") && !llvm_abiname.is_empty() { |
| 354 | llvm::LLVMRustAddModuleFlagString( | |
| 355 | llmod, | |
| 356 | llvm::LLVMModFlagBehavior::Error, | |
| 357 | c"target-abi".as_ptr(), | |
| 358 | llvm_abiname.as_ptr().cast(), | |
| 359 | llvm_abiname.len(), | |
| 360 | ); | |
| 391 | unsafe { | |
| 392 | llvm::LLVMRustAddModuleFlagString( | |
| 393 | llmod, | |
| 394 | llvm::LLVMModFlagBehavior::Error, | |
| 395 | c"target-abi".as_ptr(), | |
| 396 | llvm_abiname.as_ptr().cast(), | |
| 397 | llvm_abiname.len(), | |
| 398 | ); | |
| 399 | } | |
| 361 | 400 | } |
| 362 | 401 | |
| 363 | 402 | // Add module flags specified via -Z llvm_module_flag |
| ... | ... | @@ -375,7 +414,7 @@ pub unsafe fn create_module<'ll>( |
| 375 | 414 | // We already checked this during option parsing |
| 376 | 415 | _ => unreachable!(), |
| 377 | 416 | }; |
| 378 | llvm::LLVMRustAddModuleFlagU32(llmod, behavior, key.as_ptr().cast(), *value) | |
| 417 | unsafe { llvm::LLVMRustAddModuleFlagU32(llmod, behavior, key.as_ptr().cast(), *value) } | |
| 379 | 418 | } |
| 380 | 419 | |
| 381 | 420 | llmod |
compiler/rustc_codegen_llvm/src/lib.rs+3-3| ... | ... | @@ -216,7 +216,7 @@ impl WriteBackendMethods for LlvmCodegenBackend { |
| 216 | 216 | module: &ModuleCodegen<Self::Module>, |
| 217 | 217 | config: &ModuleConfig, |
| 218 | 218 | ) -> Result<(), FatalError> { |
| 219 | back::write::optimize(cgcx, dcx, module, config) | |
| 219 | unsafe { back::write::optimize(cgcx, dcx, module, config) } | |
| 220 | 220 | } |
| 221 | 221 | fn optimize_fat( |
| 222 | 222 | cgcx: &CodegenContext<Self>, |
| ... | ... | @@ -230,7 +230,7 @@ impl WriteBackendMethods for LlvmCodegenBackend { |
| 230 | 230 | cgcx: &CodegenContext<Self>, |
| 231 | 231 | thin: ThinModule<Self>, |
| 232 | 232 | ) -> Result<ModuleCodegen<Self::Module>, FatalError> { |
| 233 | back::lto::optimize_thin_module(thin, cgcx) | |
| 233 | unsafe { back::lto::optimize_thin_module(thin, cgcx) } | |
| 234 | 234 | } |
| 235 | 235 | unsafe fn codegen( |
| 236 | 236 | cgcx: &CodegenContext<Self>, |
| ... | ... | @@ -238,7 +238,7 @@ impl WriteBackendMethods for LlvmCodegenBackend { |
| 238 | 238 | module: ModuleCodegen<Self::Module>, |
| 239 | 239 | config: &ModuleConfig, |
| 240 | 240 | ) -> Result<CompiledModule, FatalError> { |
| 241 | back::write::codegen(cgcx, dcx, module, config) | |
| 241 | unsafe { back::write::codegen(cgcx, dcx, module, config) } | |
| 242 | 242 | } |
| 243 | 243 | fn prepare_thin( |
| 244 | 244 | module: ModuleCodegen<Self::Module>, |
compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs+38-33| ... | ... | @@ -40,7 +40,7 @@ impl<'ll> OptimizationDiagnostic<'ll> { |
| 40 | 40 | let mut filename = None; |
| 41 | 41 | let pass_name = super::build_string(|pass_name| { |
| 42 | 42 | message = super::build_string(|message| { |
| 43 | filename = super::build_string(|filename| { | |
| 43 | filename = super::build_string(|filename| unsafe { | |
| 44 | 44 | super::LLVMRustUnpackOptimizationDiagnostic( |
| 45 | 45 | di, |
| 46 | 46 | pass_name, |
| ... | ... | @@ -91,7 +91,7 @@ impl SrcMgrDiagnostic { |
| 91 | 91 | let mut ranges = [0; 8]; |
| 92 | 92 | let mut num_ranges = ranges.len() / 2; |
| 93 | 93 | let message = super::build_string(|message| { |
| 94 | buffer = super::build_string(|buffer| { | |
| 94 | buffer = super::build_string(|buffer| unsafe { | |
| 95 | 95 | have_source = super::LLVMRustUnpackSMDiagnostic( |
| 96 | 96 | diag, |
| 97 | 97 | message, |
| ... | ... | @@ -134,7 +134,9 @@ impl InlineAsmDiagnostic { |
| 134 | 134 | let mut message = None; |
| 135 | 135 | let mut level = super::DiagnosticLevel::Error; |
| 136 | 136 | |
| 137 | super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut level, &mut cookie, &mut message); | |
| 137 | unsafe { | |
| 138 | super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut level, &mut cookie, &mut message); | |
| 139 | } | |
| 138 | 140 | |
| 139 | 141 | InlineAsmDiagnostic { |
| 140 | 142 | level, |
| ... | ... | @@ -146,7 +148,8 @@ impl InlineAsmDiagnostic { |
| 146 | 148 | |
| 147 | 149 | unsafe fn unpackSrcMgr(di: &DiagnosticInfo) -> Self { |
| 148 | 150 | let mut cookie = 0; |
| 149 | let smdiag = SrcMgrDiagnostic::unpack(super::LLVMRustGetSMDiagnostic(di, &mut cookie)); | |
| 151 | let smdiag = | |
| 152 | unsafe { SrcMgrDiagnostic::unpack(super::LLVMRustGetSMDiagnostic(di, &mut cookie)) }; | |
| 150 | 153 | InlineAsmDiagnostic { |
| 151 | 154 | level: smdiag.level, |
| 152 | 155 | cookie: cookie.into(), |
| ... | ... | @@ -170,44 +173,46 @@ pub enum Diagnostic<'ll> { |
| 170 | 173 | impl<'ll> Diagnostic<'ll> { |
| 171 | 174 | pub unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self { |
| 172 | 175 | use super::DiagnosticKind as Dk; |
| 173 | let kind = super::LLVMRustGetDiagInfoKind(di); | |
| 174 | 176 | |
| 175 | match kind { | |
| 176 | Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpackInlineAsm(di)), | |
| 177 | unsafe { | |
| 178 | let kind = super::LLVMRustGetDiagInfoKind(di); | |
| 179 | match kind { | |
| 180 | Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpackInlineAsm(di)), | |
| 177 | 181 | |
| 178 | Dk::OptimizationRemark => { | |
| 179 | Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di)) | |
| 180 | } | |
| 181 | Dk::OptimizationRemarkOther => { | |
| 182 | Optimization(OptimizationDiagnostic::unpack(OptimizationRemarkOther, di)) | |
| 183 | } | |
| 184 | Dk::OptimizationRemarkMissed => { | |
| 185 | Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di)) | |
| 186 | } | |
| 182 | Dk::OptimizationRemark => { | |
| 183 | Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di)) | |
| 184 | } | |
| 185 | Dk::OptimizationRemarkOther => { | |
| 186 | Optimization(OptimizationDiagnostic::unpack(OptimizationRemarkOther, di)) | |
| 187 | } | |
| 188 | Dk::OptimizationRemarkMissed => { | |
| 189 | Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di)) | |
| 190 | } | |
| 187 | 191 | |
| 188 | Dk::OptimizationRemarkAnalysis => { | |
| 189 | Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di)) | |
| 190 | } | |
| 192 | Dk::OptimizationRemarkAnalysis => { | |
| 193 | Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di)) | |
| 194 | } | |
| 191 | 195 | |
| 192 | Dk::OptimizationRemarkAnalysisFPCommute => { | |
| 193 | Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisFPCommute, di)) | |
| 194 | } | |
| 196 | Dk::OptimizationRemarkAnalysisFPCommute => { | |
| 197 | Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisFPCommute, di)) | |
| 198 | } | |
| 195 | 199 | |
| 196 | Dk::OptimizationRemarkAnalysisAliasing => { | |
| 197 | Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisAliasing, di)) | |
| 198 | } | |
| 200 | Dk::OptimizationRemarkAnalysisAliasing => { | |
| 201 | Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisAliasing, di)) | |
| 202 | } | |
| 199 | 203 | |
| 200 | Dk::OptimizationFailure => { | |
| 201 | Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di)) | |
| 202 | } | |
| 204 | Dk::OptimizationFailure => { | |
| 205 | Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di)) | |
| 206 | } | |
| 203 | 207 | |
| 204 | Dk::PGOProfile => PGO(di), | |
| 205 | Dk::Linker => Linker(di), | |
| 206 | Dk::Unsupported => Unsupported(di), | |
| 208 | Dk::PGOProfile => PGO(di), | |
| 209 | Dk::Linker => Linker(di), | |
| 210 | Dk::Unsupported => Unsupported(di), | |
| 207 | 211 | |
| 208 | Dk::SrcMgr => InlineAsm(InlineAsmDiagnostic::unpackSrcMgr(di)), | |
| 212 | Dk::SrcMgr => InlineAsm(InlineAsmDiagnostic::unpackSrcMgr(di)), | |
| 209 | 213 | |
| 210 | _ => UnknownDiagnostic(di), | |
| 214 | _ => UnknownDiagnostic(di), | |
| 215 | } | |
| 211 | 216 | } |
| 212 | 217 | } |
| 213 | 218 | } |
compiler/rustc_codegen_llvm/src/llvm_util.rs+10-6| ... | ... | @@ -49,12 +49,16 @@ unsafe fn configure_llvm(sess: &Session) { |
| 49 | 49 | let mut llvm_c_strs = Vec::with_capacity(n_args + 1); |
| 50 | 50 | let mut llvm_args = Vec::with_capacity(n_args + 1); |
| 51 | 51 | |
| 52 | llvm::LLVMRustInstallErrorHandlers(); | |
| 52 | unsafe { | |
| 53 | llvm::LLVMRustInstallErrorHandlers(); | |
| 54 | } | |
| 53 | 55 | // On Windows, an LLVM assertion will open an Abort/Retry/Ignore dialog |
| 54 | 56 | // box for the purpose of launching a debugger. However, on CI this will |
| 55 | 57 | // cause it to hang until it times out, which can take several hours. |
| 56 | 58 | if std::env::var_os("CI").is_some() { |
| 57 | llvm::LLVMRustDisableSystemDialogsOnCrash(); | |
| 59 | unsafe { | |
| 60 | llvm::LLVMRustDisableSystemDialogsOnCrash(); | |
| 61 | } | |
| 58 | 62 | } |
| 59 | 63 | |
| 60 | 64 | fn llvm_arg_to_arg_name(full_arg: &str) -> &str { |
| ... | ... | @@ -124,12 +128,12 @@ unsafe fn configure_llvm(sess: &Session) { |
| 124 | 128 | } |
| 125 | 129 | |
| 126 | 130 | if sess.opts.unstable_opts.llvm_time_trace { |
| 127 | llvm::LLVMRustTimeTraceProfilerInitialize(); | |
| 131 | unsafe { llvm::LLVMRustTimeTraceProfilerInitialize() }; | |
| 128 | 132 | } |
| 129 | 133 | |
| 130 | 134 | rustc_llvm::initialize_available_targets(); |
| 131 | 135 | |
| 132 | llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr()); | |
| 136 | unsafe { llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr()) }; | |
| 133 | 137 | } |
| 134 | 138 | |
| 135 | 139 | pub fn time_trace_profiler_finish(file_name: &Path) { |
| ... | ... | @@ -442,8 +446,8 @@ pub(crate) fn print(req: &PrintRequest, mut out: &mut String, sess: &Session) { |
| 442 | 446 | let cpu_cstring = CString::new(handle_native(sess.target.cpu.as_ref())) |
| 443 | 447 | .unwrap_or_else(|e| bug!("failed to convert to cstring: {}", e)); |
| 444 | 448 | unsafe extern "C" fn callback(out: *mut c_void, string: *const c_char, len: usize) { |
| 445 | let out = &mut *(out as *mut &mut String); | |
| 446 | let bytes = slice::from_raw_parts(string as *const u8, len); | |
| 449 | let out = unsafe { &mut *(out as *mut &mut String) }; | |
| 450 | let bytes = unsafe { slice::from_raw_parts(string as *const u8, len) }; | |
| 447 | 451 | write!(out, "{}", String::from_utf8_lossy(bytes)).unwrap(); |
| 448 | 452 | } |
| 449 | 453 | unsafe { |
compiler/rustc_codegen_llvm/src/mono_item.rs+4-4| ... | ... | @@ -108,8 +108,8 @@ impl CodegenCx<'_, '_> { |
| 108 | 108 | llval: &llvm::Value, |
| 109 | 109 | is_declaration: bool, |
| 110 | 110 | ) -> bool { |
| 111 | let linkage = llvm::LLVMRustGetLinkage(llval); | |
| 112 | let visibility = llvm::LLVMRustGetVisibility(llval); | |
| 111 | let linkage = unsafe { llvm::LLVMRustGetLinkage(llval) }; | |
| 112 | let visibility = unsafe { llvm::LLVMRustGetVisibility(llval) }; | |
| 113 | 113 | |
| 114 | 114 | if matches!(linkage, llvm::Linkage::InternalLinkage | llvm::Linkage::PrivateLinkage) { |
| 115 | 115 | return true; |
| ... | ... | @@ -145,8 +145,8 @@ impl CodegenCx<'_, '_> { |
| 145 | 145 | } |
| 146 | 146 | |
| 147 | 147 | // Thread-local variables generally don't support copy relocations. |
| 148 | let is_thread_local_var = llvm::LLVMIsAGlobalVariable(llval) | |
| 149 | .is_some_and(|v| llvm::LLVMIsThreadLocal(v) == llvm::True); | |
| 148 | let is_thread_local_var = unsafe { llvm::LLVMIsAGlobalVariable(llval) } | |
| 149 | .is_some_and(|v| unsafe { llvm::LLVMIsThreadLocal(v) } == llvm::True); | |
| 150 | 150 | if is_thread_local_var { |
| 151 | 151 | return false; |
| 152 | 152 | } |
compiler/rustc_codegen_ssa/src/back/lto.rs+1-1| ... | ... | @@ -72,7 +72,7 @@ impl<B: WriteBackendMethods> LtoModuleCodegen<B> { |
| 72 | 72 | B::optimize_fat(cgcx, &mut module)?; |
| 73 | 73 | Ok(module) |
| 74 | 74 | } |
| 75 | LtoModuleCodegen::Thin(thin) => B::optimize_thin(cgcx, thin), | |
| 75 | LtoModuleCodegen::Thin(thin) => unsafe { B::optimize_thin(cgcx, thin) }, | |
| 76 | 76 | } |
| 77 | 77 | } |
| 78 | 78 |
compiler/rustc_llvm/src/lib.rs+1-1| ... | ... | @@ -33,7 +33,7 @@ pub unsafe extern "C" fn LLVMRustStringWriteImpl( |
| 33 | 33 | ptr: *const c_char, |
| 34 | 34 | size: size_t, |
| 35 | 35 | ) { |
| 36 | let slice = slice::from_raw_parts(ptr as *const u8, size); | |
| 36 | let slice = unsafe { slice::from_raw_parts(ptr as *const u8, size) }; | |
| 37 | 37 | |
| 38 | 38 | sr.bytes.borrow_mut().extend_from_slice(slice); |
| 39 | 39 | } |
compiler/rustc_middle/src/ty/context/tls.rs+1-1| ... | ... | @@ -67,7 +67,7 @@ fn erase(context: &ImplicitCtxt<'_, '_>) -> *const () { |
| 67 | 67 | |
| 68 | 68 | #[inline] |
| 69 | 69 | unsafe fn downcast<'a, 'tcx>(context: *const ()) -> &'a ImplicitCtxt<'a, 'tcx> { |
| 70 | &*(context as *const ImplicitCtxt<'a, 'tcx>) | |
| 70 | unsafe { &*(context as *const ImplicitCtxt<'a, 'tcx>) } | |
| 71 | 71 | } |
| 72 | 72 | |
| 73 | 73 | /// Sets `context` as the new current `ImplicitCtxt` for the duration of the function `f`. |
compiler/rustc_middle/src/ty/structural_impls.rs+17-8| ... | ... | @@ -257,7 +257,6 @@ TrivialTypeTraversalImpls! { |
| 257 | 257 | crate::ty::adjustment::PointerCoercion, |
| 258 | 258 | ::rustc_span::Span, |
| 259 | 259 | ::rustc_span::symbol::Ident, |
| 260 | ::rustc_errors::ErrorGuaranteed, | |
| 261 | 260 | ty::BoundVar, |
| 262 | 261 | ty::ValTree<'tcx>, |
| 263 | 262 | } |
| ... | ... | @@ -443,13 +442,14 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> { |
| 443 | 442 | pat.visit_with(visitor) |
| 444 | 443 | } |
| 445 | 444 | |
| 445 | ty::Error(guar) => guar.visit_with(visitor), | |
| 446 | ||
| 446 | 447 | ty::Bool |
| 447 | 448 | | ty::Char |
| 448 | 449 | | ty::Str |
| 449 | 450 | | ty::Int(_) |
| 450 | 451 | | ty::Uint(_) |
| 451 | 452 | | ty::Float(_) |
| 452 | | ty::Error(_) | |
| 453 | 453 | | ty::Infer(_) |
| 454 | 454 | | ty::Bound(..) |
| 455 | 455 | | ty::Placeholder(..) |
| ... | ... | @@ -602,6 +602,21 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> { |
| 602 | 602 | } |
| 603 | 603 | } |
| 604 | 604 | |
| 605 | impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for rustc_span::ErrorGuaranteed { | |
| 606 | fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result { | |
| 607 | visitor.visit_error(*self) | |
| 608 | } | |
| 609 | } | |
| 610 | ||
| 611 | impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for rustc_span::ErrorGuaranteed { | |
| 612 | fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( | |
| 613 | self, | |
| 614 | _folder: &mut F, | |
| 615 | ) -> Result<Self, F::Error> { | |
| 616 | Ok(self) | |
| 617 | } | |
| 618 | } | |
| 619 | ||
| 605 | 620 | impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for InferConst { |
| 606 | 621 | fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( |
| 607 | 622 | self, |
| ... | ... | @@ -617,12 +632,6 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for InferConst { |
| 617 | 632 | } |
| 618 | 633 | } |
| 619 | 634 | |
| 620 | impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::UnevaluatedConst<'tcx> { | |
| 621 | fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result { | |
| 622 | self.args.visit_with(visitor) | |
| 623 | } | |
| 624 | } | |
| 625 | ||
| 626 | 635 | impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for TyAndLayout<'tcx, Ty<'tcx>> { |
| 627 | 636 | fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result { |
| 628 | 637 | visitor.visit_ty(self.ty) |
compiler/rustc_mir_build/src/build/matches/mod.rs+19-14| ... | ... | @@ -1547,10 +1547,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { |
| 1547 | 1547 | start_block: BasicBlock, |
| 1548 | 1548 | candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>], |
| 1549 | 1549 | ) -> BlockAnd<&'b mut [&'c mut Candidate<'pat, 'tcx>]> { |
| 1550 | // We can't expand or-patterns freely. The rule is: if the candidate has an | |
| 1551 | // or-pattern as its only remaining match pair, we can expand it freely. If it has | |
| 1552 | // other match pairs, we can expand it but we can't process more candidates after | |
| 1553 | // it. | |
| 1550 | // We can't expand or-patterns freely. The rule is: | |
| 1551 | // - If a candidate doesn't start with an or-pattern, we include it in | |
| 1552 | // the expansion list as-is (i.e. it "expands" to itself). | |
| 1553 | // - If a candidate has an or-pattern as its only remaining match pair, | |
| 1554 | // we can expand it. | |
| 1555 | // - If it starts with an or-pattern but also has other match pairs, | |
| 1556 | // we can expand it, but we can't process more candidates after it. | |
| 1554 | 1557 | // |
| 1555 | 1558 | // If we didn't stop, the `otherwise` cases could get mixed up. E.g. in the |
| 1556 | 1559 | // following, or-pattern simplification (in `merge_trivial_subcandidates`) makes it |
| ... | ... | @@ -1567,17 +1570,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { |
| 1567 | 1570 | // } |
| 1568 | 1571 | // ``` |
| 1569 | 1572 | // |
| 1570 | // We therefore split the `candidates` slice in two, expand or-patterns in the first half, | |
| 1573 | // We therefore split the `candidates` slice in two, expand or-patterns in the first part, | |
| 1571 | 1574 | // and process the rest separately. |
| 1572 | let mut expand_until = 0; | |
| 1573 | for (i, candidate) in candidates.iter().enumerate() { | |
| 1574 | expand_until = i + 1; | |
| 1575 | if candidate.match_pairs.len() > 1 && candidate.starts_with_or_pattern() { | |
| 1576 | // The candidate has an or-pattern as well as more match pairs: we must | |
| 1577 | // split the candidates list here. | |
| 1578 | break; | |
| 1579 | } | |
| 1580 | } | |
| 1575 | let expand_until = candidates | |
| 1576 | .iter() | |
| 1577 | .position(|candidate| { | |
| 1578 | // If a candidate starts with an or-pattern and has more match pairs, | |
| 1579 | // we can expand it, but we must stop expanding _after_ it. | |
| 1580 | candidate.match_pairs.len() > 1 && candidate.starts_with_or_pattern() | |
| 1581 | }) | |
| 1582 | .map(|pos| pos + 1) // Stop _after_ the found candidate | |
| 1583 | .unwrap_or(candidates.len()); // Otherwise, include all candidates | |
| 1581 | 1584 | let (candidates_to_expand, remaining_candidates) = candidates.split_at_mut(expand_until); |
| 1582 | 1585 | |
| 1583 | 1586 | // Expand one level of or-patterns for each candidate in `candidates_to_expand`. |
| ... | ... | @@ -1592,6 +1595,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { |
| 1592 | 1595 | expanded_candidates.push(subcandidate); |
| 1593 | 1596 | } |
| 1594 | 1597 | } else { |
| 1598 | // A candidate that doesn't start with an or-pattern has nothing to | |
| 1599 | // expand, so it is included in the post-expansion list as-is. | |
| 1595 | 1600 | expanded_candidates.push(candidate); |
| 1596 | 1601 | } |
| 1597 | 1602 | } |
compiler/rustc_span/src/analyze_source_file.rs+58-51| ... | ... | @@ -35,25 +35,25 @@ pub fn analyze_source_file( |
| 35 | 35 | |
| 36 | 36 | cfg_match! { |
| 37 | 37 | cfg(any(target_arch = "x86", target_arch = "x86_64")) => { |
| 38 | fn analyze_source_file_dispatch(src: &str, | |
| 39 | lines: &mut Vec<RelativeBytePos>, | |
| 40 | multi_byte_chars: &mut Vec<MultiByteChar>, | |
| 41 | non_narrow_chars: &mut Vec<NonNarrowChar>) { | |
| 38 | fn analyze_source_file_dispatch( | |
| 39 | src: &str, | |
| 40 | lines: &mut Vec<RelativeBytePos>, | |
| 41 | multi_byte_chars: &mut Vec<MultiByteChar>, | |
| 42 | non_narrow_chars: &mut Vec<NonNarrowChar>, | |
| 43 | ) { | |
| 42 | 44 | if is_x86_feature_detected!("sse2") { |
| 43 | 45 | unsafe { |
| 44 | analyze_source_file_sse2(src, | |
| 45 | lines, | |
| 46 | multi_byte_chars, | |
| 47 | non_narrow_chars); | |
| 46 | analyze_source_file_sse2(src, lines, multi_byte_chars, non_narrow_chars); | |
| 48 | 47 | } |
| 49 | 48 | } else { |
| 50 | analyze_source_file_generic(src, | |
| 51 | src.len(), | |
| 52 | RelativeBytePos::from_u32(0), | |
| 53 | lines, | |
| 54 | multi_byte_chars, | |
| 55 | non_narrow_chars); | |
| 56 | ||
| 49 | analyze_source_file_generic( | |
| 50 | src, | |
| 51 | src.len(), | |
| 52 | RelativeBytePos::from_u32(0), | |
| 53 | lines, | |
| 54 | multi_byte_chars, | |
| 55 | non_narrow_chars, | |
| 56 | ); | |
| 57 | 57 | } |
| 58 | 58 | } |
| 59 | 59 | |
| ... | ... | @@ -62,10 +62,12 @@ cfg_match! { |
| 62 | 62 | /// function falls back to the generic implementation. Otherwise it uses |
| 63 | 63 | /// SSE2 intrinsics to quickly find all newlines. |
| 64 | 64 | #[target_feature(enable = "sse2")] |
| 65 | unsafe fn analyze_source_file_sse2(src: &str, | |
| 66 | lines: &mut Vec<RelativeBytePos>, | |
| 67 | multi_byte_chars: &mut Vec<MultiByteChar>, | |
| 68 | non_narrow_chars: &mut Vec<NonNarrowChar>) { | |
| 65 | unsafe fn analyze_source_file_sse2( | |
| 66 | src: &str, | |
| 67 | lines: &mut Vec<RelativeBytePos>, | |
| 68 | multi_byte_chars: &mut Vec<MultiByteChar>, | |
| 69 | non_narrow_chars: &mut Vec<NonNarrowChar>, | |
| 70 | ) { | |
| 69 | 71 | #[cfg(target_arch = "x86")] |
| 70 | 72 | use std::arch::x86::*; |
| 71 | 73 | #[cfg(target_arch = "x86_64")] |
| ... | ... | @@ -83,17 +85,17 @@ cfg_match! { |
| 83 | 85 | // handled it. |
| 84 | 86 | let mut intra_chunk_offset = 0; |
| 85 | 87 | |
| 86 | for chunk_index in 0 .. chunk_count { | |
| 88 | for chunk_index in 0..chunk_count { | |
| 87 | 89 | let ptr = src_bytes.as_ptr() as *const __m128i; |
| 88 | 90 | // We don't know if the pointer is aligned to 16 bytes, so we |
| 89 | 91 | // use `loadu`, which supports unaligned loading. |
| 90 | let chunk = _mm_loadu_si128(ptr.add(chunk_index)); | |
| 92 | let chunk = unsafe { _mm_loadu_si128(ptr.add(chunk_index)) }; | |
| 91 | 93 | |
| 92 | 94 | // For character in the chunk, see if its byte value is < 0, which |
| 93 | 95 | // indicates that it's part of a UTF-8 char. |
| 94 | let multibyte_test = _mm_cmplt_epi8(chunk, _mm_set1_epi8(0)); | |
| 96 | let multibyte_test = unsafe { _mm_cmplt_epi8(chunk, _mm_set1_epi8(0)) }; | |
| 95 | 97 | // Create a bit mask from the comparison results. |
| 96 | let multibyte_mask = _mm_movemask_epi8(multibyte_test); | |
| 98 | let multibyte_mask = unsafe { _mm_movemask_epi8(multibyte_test) }; | |
| 97 | 99 | |
| 98 | 100 | // If the bit mask is all zero, we only have ASCII chars here: |
| 99 | 101 | if multibyte_mask == 0 { |
| ... | ... | @@ -102,19 +104,19 @@ cfg_match! { |
| 102 | 104 | // Check if there are any control characters in the chunk. All |
| 103 | 105 | // control characters that we can encounter at this point have a |
| 104 | 106 | // byte value less than 32 or ... |
| 105 | let control_char_test0 = _mm_cmplt_epi8(chunk, _mm_set1_epi8(32)); | |
| 106 | let control_char_mask0 = _mm_movemask_epi8(control_char_test0); | |
| 107 | let control_char_test0 = unsafe { _mm_cmplt_epi8(chunk, _mm_set1_epi8(32)) }; | |
| 108 | let control_char_mask0 = unsafe { _mm_movemask_epi8(control_char_test0) }; | |
| 107 | 109 | |
| 108 | 110 | // ... it's the ASCII 'DEL' character with a value of 127. |
| 109 | let control_char_test1 = _mm_cmpeq_epi8(chunk, _mm_set1_epi8(127)); | |
| 110 | let control_char_mask1 = _mm_movemask_epi8(control_char_test1); | |
| 111 | let control_char_test1 = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(127)) }; | |
| 112 | let control_char_mask1 = unsafe { _mm_movemask_epi8(control_char_test1) }; | |
| 111 | 113 | |
| 112 | 114 | let control_char_mask = control_char_mask0 | control_char_mask1; |
| 113 | 115 | |
| 114 | 116 | if control_char_mask != 0 { |
| 115 | 117 | // Check for newlines in the chunk |
| 116 | let newlines_test = _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)); | |
| 117 | let newlines_mask = _mm_movemask_epi8(newlines_test); | |
| 118 | let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) }; | |
| 119 | let newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) }; | |
| 118 | 120 | |
| 119 | 121 | if control_char_mask == newlines_mask { |
| 120 | 122 | // All control characters are newlines, record them |
| ... | ... | @@ -126,7 +128,7 @@ cfg_match! { |
| 126 | 128 | |
| 127 | 129 | if index >= CHUNK_SIZE as u32 { |
| 128 | 130 | // We have arrived at the end of the chunk. |
| 129 | break | |
| 131 | break; | |
| 130 | 132 | } |
| 131 | 133 | |
| 132 | 134 | lines.push(RelativeBytePos(index) + output_offset); |
| ... | ... | @@ -137,14 +139,14 @@ cfg_match! { |
| 137 | 139 | |
| 138 | 140 | // We are done for this chunk. All control characters were |
| 139 | 141 | // newlines and we took care of those. |
| 140 | continue | |
| 142 | continue; | |
| 141 | 143 | } else { |
| 142 | 144 | // Some of the control characters are not newlines, |
| 143 | 145 | // fall through to the slow path below. |
| 144 | 146 | } |
| 145 | 147 | } else { |
| 146 | 148 | // No control characters, nothing to record for this chunk |
| 147 | continue | |
| 149 | continue; | |
| 148 | 150 | } |
| 149 | 151 | } |
| 150 | 152 | |
| ... | ... | @@ -152,43 +154,48 @@ cfg_match! { |
| 152 | 154 | // There are control chars in here, fallback to generic decoding. |
| 153 | 155 | let scan_start = chunk_index * CHUNK_SIZE + intra_chunk_offset; |
| 154 | 156 | intra_chunk_offset = analyze_source_file_generic( |
| 155 | &src[scan_start .. ], | |
| 157 | &src[scan_start..], | |
| 156 | 158 | CHUNK_SIZE - intra_chunk_offset, |
| 157 | 159 | RelativeBytePos::from_usize(scan_start), |
| 158 | 160 | lines, |
| 159 | 161 | multi_byte_chars, |
| 160 | non_narrow_chars | |
| 162 | non_narrow_chars, | |
| 161 | 163 | ); |
| 162 | 164 | } |
| 163 | 165 | |
| 164 | 166 | // There might still be a tail left to analyze |
| 165 | 167 | let tail_start = chunk_count * CHUNK_SIZE + intra_chunk_offset; |
| 166 | 168 | if tail_start < src.len() { |
| 167 | analyze_source_file_generic(&src[tail_start ..], | |
| 168 | src.len() - tail_start, | |
| 169 | RelativeBytePos::from_usize(tail_start), | |
| 170 | lines, | |
| 171 | multi_byte_chars, | |
| 172 | non_narrow_chars); | |
| 169 | analyze_source_file_generic( | |
| 170 | &src[tail_start..], | |
| 171 | src.len() - tail_start, | |
| 172 | RelativeBytePos::from_usize(tail_start), | |
| 173 | lines, | |
| 174 | multi_byte_chars, | |
| 175 | non_narrow_chars, | |
| 176 | ); | |
| 173 | 177 | } |
| 174 | 178 | } |
| 175 | 179 | } |
| 176 | 180 | _ => { |
| 177 | 181 | // The target (or compiler version) does not support SSE2 ... |
| 178 | fn analyze_source_file_dispatch(src: &str, | |
| 179 | lines: &mut Vec<RelativeBytePos>, | |
| 180 | multi_byte_chars: &mut Vec<MultiByteChar>, | |
| 181 | non_narrow_chars: &mut Vec<NonNarrowChar>) { | |
| 182 | analyze_source_file_generic(src, | |
| 183 | src.len(), | |
| 184 | RelativeBytePos::from_u32(0), | |
| 185 | lines, | |
| 186 | multi_byte_chars, | |
| 187 | non_narrow_chars); | |
| 182 | fn analyze_source_file_dispatch( | |
| 183 | src: &str, | |
| 184 | lines: &mut Vec<RelativeBytePos>, | |
| 185 | multi_byte_chars: &mut Vec<MultiByteChar>, | |
| 186 | non_narrow_chars: &mut Vec<NonNarrowChar>, | |
| 187 | ) { | |
| 188 | analyze_source_file_generic( | |
| 189 | src, | |
| 190 | src.len(), | |
| 191 | RelativeBytePos::from_u32(0), | |
| 192 | lines, | |
| 193 | multi_byte_chars, | |
| 194 | non_narrow_chars, | |
| 195 | ); | |
| 188 | 196 | } |
| 189 | 197 | } |
| 190 | 198 | } |
| 191 | ||
| 192 | 199 | // `scan_len` determines the number of bytes in `src` to scan. Note that the |
| 193 | 200 | // function can read past `scan_len` if a multi-byte character start within the |
| 194 | 201 | // range but extends past it. The overflow is returned by the function. |
compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs+3-1| ... | ... | @@ -466,7 +466,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { |
| 466 | 466 | && let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(expr) |
| 467 | 467 | { |
| 468 | 468 | // Suggest dereferencing the argument to a function/method call if possible |
| 469 | ||
| 470 | 469 | let mut real_trait_pred = trait_pred; |
| 471 | 470 | while let Some((parent_code, parent_trait_pred)) = code.parent() { |
| 472 | 471 | code = parent_code; |
| ... | ... | @@ -553,6 +552,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { |
| 553 | 552 | ); |
| 554 | 553 | if self.predicate_may_hold(&obligation) |
| 555 | 554 | && self.predicate_must_hold_modulo_regions(&sized_obligation) |
| 555 | // Do not suggest * if it is already a reference, | |
| 556 | // will suggest removing the borrow instead in that case. | |
| 557 | && !matches!(expr.kind, hir::ExprKind::AddrOf(..)) | |
| 556 | 558 | { |
| 557 | 559 | let call_node = self.tcx.hir_node(*call_hir_id); |
| 558 | 560 | let msg = "consider dereferencing here"; |
compiler/rustc_type_ir/src/visit.rs+21-24| ... | ... | @@ -101,8 +101,12 @@ pub trait TypeVisitor<I: Interner>: Sized { |
| 101 | 101 | |
| 102 | 102 | // The default region visitor is a no-op because `Region` is non-recursive |
| 103 | 103 | // and has no `super_visit_with` method to call. |
| 104 | fn visit_region(&mut self, _r: I::Region) -> Self::Result { | |
| 105 | Self::Result::output() | |
| 104 | fn visit_region(&mut self, r: I::Region) -> Self::Result { | |
| 105 | if let ty::ReError(guar) = r.kind() { | |
| 106 | self.visit_error(guar) | |
| 107 | } else { | |
| 108 | Self::Result::output() | |
| 109 | } | |
| 106 | 110 | } |
| 107 | 111 | |
| 108 | 112 | fn visit_const(&mut self, c: I::Const) -> Self::Result { |
| ... | ... | @@ -116,6 +120,10 @@ pub trait TypeVisitor<I: Interner>: Sized { |
| 116 | 120 | fn visit_clauses(&mut self, p: I::Clauses) -> Self::Result { |
| 117 | 121 | p.super_visit_with(self) |
| 118 | 122 | } |
| 123 | ||
| 124 | fn visit_error(&mut self, _guar: I::ErrorGuaranteed) -> Self::Result { | |
| 125 | Self::Result::output() | |
| 126 | } | |
| 119 | 127 | } |
| 120 | 128 | |
| 121 | 129 | /////////////////////////////////////////////////////////////////////////// |
| ... | ... | @@ -439,6 +447,15 @@ impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor { |
| 439 | 447 | ControlFlow::Continue(()) |
| 440 | 448 | } |
| 441 | 449 | } |
| 450 | ||
| 451 | #[inline] | |
| 452 | fn visit_error(&mut self, _guar: <I as Interner>::ErrorGuaranteed) -> Self::Result { | |
| 453 | if self.flags.intersects(TypeFlags::HAS_ERROR) { | |
| 454 | ControlFlow::Break(FoundFlags) | |
| 455 | } else { | |
| 456 | ControlFlow::Continue(()) | |
| 457 | } | |
| 458 | } | |
| 442 | 459 | } |
| 443 | 460 | |
| 444 | 461 | #[derive(Debug, PartialEq, Eq, Copy, Clone)] |
| ... | ... | @@ -547,27 +564,7 @@ struct HasErrorVisitor; |
| 547 | 564 | impl<I: Interner> TypeVisitor<I> for HasErrorVisitor { |
| 548 | 565 | type Result = ControlFlow<I::ErrorGuaranteed>; |
| 549 | 566 | |
| 550 | fn visit_ty(&mut self, t: <I as Interner>::Ty) -> Self::Result { | |
| 551 | if let ty::Error(guar) = t.kind() { | |
| 552 | ControlFlow::Break(guar) | |
| 553 | } else { | |
| 554 | t.super_visit_with(self) | |
| 555 | } | |
| 556 | } | |
| 557 | ||
| 558 | fn visit_const(&mut self, c: <I as Interner>::Const) -> Self::Result { | |
| 559 | if let ty::ConstKind::Error(guar) = c.kind() { | |
| 560 | ControlFlow::Break(guar) | |
| 561 | } else { | |
| 562 | c.super_visit_with(self) | |
| 563 | } | |
| 564 | } | |
| 565 | ||
| 566 | fn visit_region(&mut self, r: <I as Interner>::Region) -> Self::Result { | |
| 567 | if let ty::ReError(guar) = r.kind() { | |
| 568 | ControlFlow::Break(guar) | |
| 569 | } else { | |
| 570 | ControlFlow::Continue(()) | |
| 571 | } | |
| 567 | fn visit_error(&mut self, guar: <I as Interner>::ErrorGuaranteed) -> Self::Result { | |
| 568 | ControlFlow::Break(guar) | |
| 572 | 569 | } |
| 573 | 570 | } |
library/std/src/sys/pal/teeos/alloc.rs+9-9| ... | ... | @@ -11,9 +11,9 @@ unsafe impl GlobalAlloc for System { |
| 11 | 11 | // Also see <https://github.com/rust-lang/rust/issues/45955> and |
| 12 | 12 | // <https://github.com/rust-lang/rust/issues/62251#issuecomment-507580914>. |
| 13 | 13 | if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { |
| 14 | libc::malloc(layout.size()) as *mut u8 | |
| 14 | unsafe { libc::malloc(layout.size()) as *mut u8 } | |
| 15 | 15 | } else { |
| 16 | aligned_malloc(&layout) | |
| 16 | unsafe { aligned_malloc(&layout) } | |
| 17 | 17 | } |
| 18 | 18 | } |
| 19 | 19 | |
| ... | ... | @@ -21,11 +21,11 @@ unsafe impl GlobalAlloc for System { |
| 21 | 21 | unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { |
| 22 | 22 | // See the comment above in `alloc` for why this check looks the way it does. |
| 23 | 23 | if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { |
| 24 | libc::calloc(layout.size(), 1) as *mut u8 | |
| 24 | unsafe { libc::calloc(layout.size(), 1) as *mut u8 } | |
| 25 | 25 | } else { |
| 26 | let ptr = self.alloc(layout); | |
| 26 | let ptr = unsafe { self.alloc(layout) }; | |
| 27 | 27 | if !ptr.is_null() { |
| 28 | ptr::write_bytes(ptr, 0, layout.size()); | |
| 28 | unsafe { ptr::write_bytes(ptr, 0, layout.size()) }; | |
| 29 | 29 | } |
| 30 | 30 | ptr |
| 31 | 31 | } |
| ... | ... | @@ -33,15 +33,15 @@ unsafe impl GlobalAlloc for System { |
| 33 | 33 | |
| 34 | 34 | #[inline] |
| 35 | 35 | unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { |
| 36 | libc::free(ptr as *mut libc::c_void) | |
| 36 | unsafe { libc::free(ptr as *mut libc::c_void) } | |
| 37 | 37 | } |
| 38 | 38 | |
| 39 | 39 | #[inline] |
| 40 | 40 | unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { |
| 41 | 41 | if layout.align() <= MIN_ALIGN && layout.align() <= new_size { |
| 42 | libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 | |
| 42 | unsafe { libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 } | |
| 43 | 43 | } else { |
| 44 | realloc_fallback(self, ptr, layout, new_size) | |
| 44 | unsafe { realloc_fallback(self, ptr, layout, new_size) } | |
| 45 | 45 | } |
| 46 | 46 | } |
| 47 | 47 | } |
| ... | ... | @@ -52,6 +52,6 @@ unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { |
| 52 | 52 | // posix_memalign requires that the alignment be a multiple of `sizeof(void*)`. |
| 53 | 53 | // Since these are all powers of 2, we can just use max. |
| 54 | 54 | let align = layout.align().max(crate::mem::size_of::<usize>()); |
| 55 | let ret = libc::posix_memalign(&mut out, align, layout.size()); | |
| 55 | let ret = unsafe { libc::posix_memalign(&mut out, align, layout.size()) }; | |
| 56 | 56 | if ret != 0 { ptr::null_mut() } else { out as *mut u8 } |
| 57 | 57 | } |
library/std/src/sys/pal/teeos/mod.rs+1-1| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | //! |
| 3 | 3 | //! This module contains the facade (aka platform-specific) implementations of |
| 4 | 4 | //! OS level functionality for Teeos. |
| 5 | #![allow(unsafe_op_in_unsafe_fn)] | |
| 5 | #![deny(unsafe_op_in_unsafe_fn)] | |
| 6 | 6 | #![allow(unused_variables)] |
| 7 | 7 | #![allow(dead_code)] |
| 8 | 8 |
library/std/src/sys/pal/teeos/thread.rs+15-13| ... | ... | @@ -28,22 +28,24 @@ impl Thread { |
| 28 | 28 | // unsafe: see thread::Builder::spawn_unchecked for safety requirements |
| 29 | 29 | pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> { |
| 30 | 30 | let p = Box::into_raw(Box::new(p)); |
| 31 | let mut native: libc::pthread_t = mem::zeroed(); | |
| 32 | let mut attr: libc::pthread_attr_t = mem::zeroed(); | |
| 33 | assert_eq!(libc::pthread_attr_init(&mut attr), 0); | |
| 31 | let mut native: libc::pthread_t = unsafe { mem::zeroed() }; | |
| 32 | let mut attr: libc::pthread_attr_t = unsafe { mem::zeroed() }; | |
| 33 | assert_eq!(unsafe { libc::pthread_attr_init(&mut attr) }, 0); | |
| 34 | 34 | assert_eq!( |
| 35 | libc::pthread_attr_settee( | |
| 36 | &mut attr, | |
| 37 | libc::TEESMP_THREAD_ATTR_CA_INHERIT, | |
| 38 | libc::TEESMP_THREAD_ATTR_TASK_ID_INHERIT, | |
| 39 | libc::TEESMP_THREAD_ATTR_HAS_SHADOW, | |
| 40 | ), | |
| 35 | unsafe { | |
| 36 | libc::pthread_attr_settee( | |
| 37 | &mut attr, | |
| 38 | libc::TEESMP_THREAD_ATTR_CA_INHERIT, | |
| 39 | libc::TEESMP_THREAD_ATTR_TASK_ID_INHERIT, | |
| 40 | libc::TEESMP_THREAD_ATTR_HAS_SHADOW, | |
| 41 | ) | |
| 42 | }, | |
| 41 | 43 | 0, |
| 42 | 44 | ); |
| 43 | 45 | |
| 44 | 46 | let stack_size = cmp::max(stack, min_stack_size(&attr)); |
| 45 | 47 | |
| 46 | match libc::pthread_attr_setstacksize(&mut attr, stack_size) { | |
| 48 | match unsafe { libc::pthread_attr_setstacksize(&mut attr, stack_size) } { | |
| 47 | 49 | 0 => {} |
| 48 | 50 | n => { |
| 49 | 51 | assert_eq!(n, libc::EINVAL); |
| ... | ... | @@ -54,7 +56,7 @@ impl Thread { |
| 54 | 56 | let page_size = os::page_size(); |
| 55 | 57 | let stack_size = |
| 56 | 58 | (stack_size + page_size - 1) & (-(page_size as isize - 1) as usize - 1); |
| 57 | assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0); | |
| 59 | assert_eq!(unsafe { libc::pthread_attr_setstacksize(&mut attr, stack_size) }, 0); | |
| 58 | 60 | } |
| 59 | 61 | }; |
| 60 | 62 | |
| ... | ... | @@ -62,12 +64,12 @@ impl Thread { |
| 62 | 64 | // Note: if the thread creation fails and this assert fails, then p will |
| 63 | 65 | // be leaked. However, an alternative design could cause double-free |
| 64 | 66 | // which is clearly worse. |
| 65 | assert_eq!(libc::pthread_attr_destroy(&mut attr), 0); | |
| 67 | assert_eq!(unsafe { libc::pthread_attr_destroy(&mut attr) }, 0); | |
| 66 | 68 | |
| 67 | 69 | return if ret != 0 { |
| 68 | 70 | // The thread failed to start and as a result p was not consumed. Therefore, it is |
| 69 | 71 | // safe to reconstruct the box so that it gets deallocated. |
| 70 | drop(Box::from_raw(p)); | |
| 72 | drop(unsafe { Box::from_raw(p) }); | |
| 71 | 73 | Err(io::Error::from_raw_os_error(ret)) |
| 72 | 74 | } else { |
| 73 | 75 | // The new thread will start running earliest after the next yield. |
library/std/src/sys/sync/condvar/teeos.rs+4-4| ... | ... | @@ -76,16 +76,16 @@ impl Condvar { |
| 76 | 76 | |
| 77 | 77 | #[inline] |
| 78 | 78 | pub unsafe fn wait(&self, mutex: &Mutex) { |
| 79 | let mutex = mutex::raw(mutex); | |
| 79 | let mutex = unsafe { mutex::raw(mutex) }; | |
| 80 | 80 | self.verify(mutex); |
| 81 | let r = libc::pthread_cond_wait(raw(self), mutex); | |
| 81 | let r = unsafe { libc::pthread_cond_wait(raw(self), mutex) }; | |
| 82 | 82 | debug_assert_eq!(r, 0); |
| 83 | 83 | } |
| 84 | 84 | |
| 85 | 85 | pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { |
| 86 | 86 | use crate::sys::time::Timespec; |
| 87 | 87 | |
| 88 | let mutex = mutex::raw(mutex); | |
| 88 | let mutex = unsafe { mutex::raw(mutex) }; | |
| 89 | 89 | self.verify(mutex); |
| 90 | 90 | |
| 91 | 91 | let timeout = Timespec::now(libc::CLOCK_MONOTONIC) |
| ... | ... | @@ -93,7 +93,7 @@ impl Condvar { |
| 93 | 93 | .and_then(|t| t.to_timespec()) |
| 94 | 94 | .unwrap_or(TIMESPEC_MAX); |
| 95 | 95 | |
| 96 | let r = pthread_cond_timedwait(raw(self), mutex, &timeout); | |
| 96 | let r = unsafe { pthread_cond_timedwait(raw(self), mutex, &timeout) }; | |
| 97 | 97 | assert!(r == libc::ETIMEDOUT || r == 0); |
| 98 | 98 | r == 0 |
| 99 | 99 | } |
src/bootstrap/src/core/builder.rs+1| ... | ... | @@ -2001,6 +2001,7 @@ impl<'a> Builder<'a> { |
| 2001 | 2001 | // FIXME(edition_2024): Change this to `-Wrust_2024_idioms` when all |
| 2002 | 2002 | // of the individual lints are satisfied. |
| 2003 | 2003 | rustflags.arg("-Wkeyword_idents_2024"); |
| 2004 | rustflags.arg("-Wunsafe_op_in_unsafe_fn"); | |
| 2004 | 2005 | } |
| 2005 | 2006 | |
| 2006 | 2007 | if self.config.rust_frame_pointers { |
src/tools/run-make-support/Cargo.toml+1-1| ... | ... | @@ -9,7 +9,7 @@ object = "0.34.0" |
| 9 | 9 | similar = "2.5.0" |
| 10 | 10 | wasmparser = "0.118.2" |
| 11 | 11 | regex = "1.8" # 1.8 to avoid memchr 2.6.0, as 2.5.0 is pinned in the workspace |
| 12 | gimli = "0.28.1" | |
| 12 | gimli = "0.31.0" | |
| 13 | 13 | ar = "0.9.0" |
| 14 | 14 | |
| 15 | 15 | build_helper = { path = "../build_helper" } |
tests/ui/traits/suggest-dereferences/invalid-suggest-deref-issue-127590.rs created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | fn main() { | |
| 2 | let fields = vec![1]; | |
| 3 | let variant = vec![2]; | |
| 4 | ||
| 5 | // should not suggest `*&variant.iter()` | |
| 6 | for (src, dest) in std::iter::zip(fields.iter(), &variant.iter()) { | |
| 7 | //~^ ERROR `&std::slice::Iter<'_, {integer}>` is not an iterator | |
| 8 | //~| ERROR `&std::slice::Iter<'_, {integer}>` is not an iterator | |
| 9 | eprintln!("{} {}", src, dest); | |
| 10 | } | |
| 11 | ||
| 12 | // don't suggest add `variant.iter().clone().clone()` | |
| 13 | for (src, dest) in std::iter::zip(fields.iter(), &variant.iter().clone()) { | |
| 14 | //~^ ERROR `&std::slice::Iter<'_, {integer}>` is not an iterator | |
| 15 | //~| ERROR `&std::slice::Iter<'_, {integer}>` is not an iterator | |
| 16 | eprintln!("{} {}", src, dest); | |
| 17 | } | |
| 18 | } |
tests/ui/traits/suggest-dereferences/invalid-suggest-deref-issue-127590.stderr created+61| ... | ... | @@ -0,0 +1,61 @@ |
| 1 | error[E0277]: `&std::slice::Iter<'_, {integer}>` is not an iterator | |
| 2 | --> $DIR/invalid-suggest-deref-issue-127590.rs:6:54 | |
| 3 | | | |
| 4 | LL | for (src, dest) in std::iter::zip(fields.iter(), &variant.iter()) { | |
| 5 | | -------------- ^^^^^^^^^^^^^^^ `&std::slice::Iter<'_, {integer}>` is not an iterator | |
| 6 | | | | |
| 7 | | required by a bound introduced by this call | |
| 8 | | | |
| 9 | = help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`, which is required by `&std::slice::Iter<'_, {integer}>: IntoIterator` | |
| 10 | = note: required for `&std::slice::Iter<'_, {integer}>` to implement `IntoIterator` | |
| 11 | note: required by a bound in `std::iter::zip` | |
| 12 | --> $SRC_DIR/core/src/iter/adapters/zip.rs:LL:COL | |
| 13 | help: consider removing the leading `&`-reference | |
| 14 | | | |
| 15 | LL - for (src, dest) in std::iter::zip(fields.iter(), &variant.iter()) { | |
| 16 | LL + for (src, dest) in std::iter::zip(fields.iter(), variant.iter()) { | |
| 17 | | | |
| 18 | ||
| 19 | error[E0277]: `&std::slice::Iter<'_, {integer}>` is not an iterator | |
| 20 | --> $DIR/invalid-suggest-deref-issue-127590.rs:6:24 | |
| 21 | | | |
| 22 | LL | for (src, dest) in std::iter::zip(fields.iter(), &variant.iter()) { | |
| 23 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&std::slice::Iter<'_, {integer}>` is not an iterator | |
| 24 | | | |
| 25 | = help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`, which is required by `Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>: IntoIterator` | |
| 26 | = help: the trait `Iterator` is implemented for `std::slice::Iter<'a, T>` | |
| 27 | = note: required for `Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>` to implement `Iterator` | |
| 28 | = note: required for `Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>` to implement `IntoIterator` | |
| 29 | ||
| 30 | error[E0277]: `&std::slice::Iter<'_, {integer}>` is not an iterator | |
| 31 | --> $DIR/invalid-suggest-deref-issue-127590.rs:13:54 | |
| 32 | | | |
| 33 | LL | for (src, dest) in std::iter::zip(fields.iter(), &variant.iter().clone()) { | |
| 34 | | -------------- ^^^^^^^^^^^^^^^^^^^^^^^ `&std::slice::Iter<'_, {integer}>` is not an iterator | |
| 35 | | | | |
| 36 | | required by a bound introduced by this call | |
| 37 | | | |
| 38 | = help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`, which is required by `&std::slice::Iter<'_, {integer}>: IntoIterator` | |
| 39 | = note: required for `&std::slice::Iter<'_, {integer}>` to implement `IntoIterator` | |
| 40 | note: required by a bound in `std::iter::zip` | |
| 41 | --> $SRC_DIR/core/src/iter/adapters/zip.rs:LL:COL | |
| 42 | help: consider removing the leading `&`-reference | |
| 43 | | | |
| 44 | LL - for (src, dest) in std::iter::zip(fields.iter(), &variant.iter().clone()) { | |
| 45 | LL + for (src, dest) in std::iter::zip(fields.iter(), variant.iter().clone()) { | |
| 46 | | | |
| 47 | ||
| 48 | error[E0277]: `&std::slice::Iter<'_, {integer}>` is not an iterator | |
| 49 | --> $DIR/invalid-suggest-deref-issue-127590.rs:13:24 | |
| 50 | | | |
| 51 | LL | for (src, dest) in std::iter::zip(fields.iter(), &variant.iter().clone()) { | |
| 52 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&std::slice::Iter<'_, {integer}>` is not an iterator | |
| 53 | | | |
| 54 | = help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`, which is required by `Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>: IntoIterator` | |
| 55 | = help: the trait `Iterator` is implemented for `std::slice::Iter<'a, T>` | |
| 56 | = note: required for `Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>` to implement `Iterator` | |
| 57 | = note: required for `Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>` to implement `IntoIterator` | |
| 58 | ||
| 59 | error: aborting due to 4 previous errors | |
| 60 | ||
| 61 | For more information about this error, try `rustc --explain E0277`. |