From 03e64f409f6aea697e43e3985353d7796cd102f2 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 28 Jun 2023 18:08:54 -0700 Subject: [PATCH 01/18] style-guide: Document newline rules for assignment operators The style guide gives general rules for binary operators including assignment, and one of those rules says to put the operator on the subsequent line; the style guide needs to explicitly state the exception of breaking *after* assignment operators rather than before. This is already what rustfmt does and what users do; this fixes the style guide to match the expected default style. --- src/doc/style-guide/src/expressions.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index 8271b42da4c70..0edf848c1e602 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -294,8 +294,9 @@ Use parentheses liberally, do not necessarily elide them due to precedence. Tools should not automatically insert or remove parentheses. Do not use spaces to indicate precedence. -If line-breaking, put the operator on a new line and block indent. Put each -sub-expression on its own line. E.g., +If line-breaking, block-indent each subsequent line. For assignment operators, +break after the operator; for all other operators, put the operator on the +subsequent line. Put each sub-expression on its own line: ```rust foo_bar From bf5eaa45506bbaa5fe9322c4e114d89fd87ad5f4 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Tue, 9 May 2023 10:02:59 +0000 Subject: [PATCH 02/18] llvm ffi: Expose `CallInst->setTailCallKind` --- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 11 ++++++++ .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 26 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 6ef3418cc5f77..1883a8aa0a344 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -585,6 +585,16 @@ pub enum ThreadLocalMode { LocalExec, } +/// LLVMRustTailCallKind +#[derive(Copy, Clone)] +#[repr(C)] +pub enum TailCallKind { + None, + Tail, + MustTail, + NoTail, +} + /// LLVMRustChecksumKind #[derive(Copy, Clone)] #[repr(C)] @@ -1195,6 +1205,7 @@ extern "C" { NameLen: size_t, ) -> Option<&Value>; pub fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool); + pub fn LLVMRustSetTailCallKind(CallInst: &Value, TKC: TailCallKind); // Operations on attributes pub fn LLVMRustCreateAttrNoValue(C: &Context, attr: AttributeKind) -> &Attribute; diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index ea04899ab6872..3a43fa415bbc4 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -116,6 +116,32 @@ extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name, return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen))); } +enum class LLVMRustTailCallKind { + None, + Tail, + MustTail, + NoTail, +}; + +static CallInst::TailCallKind fromRust(LLVMRustTailCallKind Kind) { + switch (Kind) { + case LLVMRustTailCallKind::None: + return CallInst::TailCallKind::TCK_None; + case LLVMRustTailCallKind::Tail: + return CallInst::TailCallKind::TCK_Tail; + case LLVMRustTailCallKind::MustTail: + return CallInst::TailCallKind::TCK_MustTail; + case LLVMRustTailCallKind::NoTail: + return CallInst::TailCallKind::TCK_NoTail; + default: + report_fatal_error("bad CallInst::TailCallKind."); + } +} + +extern "C" void LLVMRustSetTailCallKind(LLVMValueRef Call, LLVMRustTailCallKind TCK) { + unwrap(Call)->setTailCallKind(fromRust(TCK)); +} + extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M, const char *Name, size_t NameLen, From f25463e8483d8dcfb64cda4e96d5b4fbd11a19c8 Mon Sep 17 00:00:00 2001 From: yukang Date: Wed, 5 Jul 2023 16:25:46 +0800 Subject: [PATCH 03/18] Fix the issue of wrong diagnosis for extern pub fn --- compiler/rustc_parse/src/parser/item.rs | 6 +++++- tests/ui/parser/issue-113342.rs | 9 +++++++++ tests/ui/parser/issue-113342.stderr | 11 +++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 tests/ui/parser/issue-113342.rs create mode 100644 tests/ui/parser/issue-113342.stderr diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 3783ec41b7e23..1470180dea714 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2182,7 +2182,11 @@ impl<'a> Parser<'a> { // `extern ABI fn` || self.check_keyword_case(kw::Extern, case) && self.look_ahead(1, |t| t.can_begin_literal_maybe_minus()) - && self.look_ahead(2, |t| t.is_keyword_case(kw::Fn, case)) + && (self.look_ahead(2, |t| t.is_keyword_case(kw::Fn, case)) || + // this branch is only for better diagnostic in later, `pub` is not allowed here + (self.may_recover() + && self.look_ahead(2, |t| t.is_keyword(kw::Pub)) + && self.look_ahead(3, |t| t.is_keyword_case(kw::Fn, case)))) } /// Parses all the "front matter" (or "qualifiers") for a `fn` declaration, diff --git a/tests/ui/parser/issue-113342.rs b/tests/ui/parser/issue-113342.rs new file mode 100644 index 0000000000000..18b502736f7ba --- /dev/null +++ b/tests/ui/parser/issue-113342.rs @@ -0,0 +1,9 @@ +#[link(name = "my_c_library")] +extern "C" { + fn my_c_function(x: i32) -> bool; +} + +#[no_mangle] +extern "C" pub fn id(x: i32) -> i32 { x } //~ ERROR expected `fn`, found keyword `pub` + +fn main() {} diff --git a/tests/ui/parser/issue-113342.stderr b/tests/ui/parser/issue-113342.stderr new file mode 100644 index 0000000000000..a0c5e665ff8f7 --- /dev/null +++ b/tests/ui/parser/issue-113342.stderr @@ -0,0 +1,11 @@ +error: expected `fn`, found keyword `pub` + --> $DIR/issue-113342.rs:7:12 + | +LL | extern "C" pub fn id(x: i32) -> i32 { x } + | -----------^^^ + | | | + | | expected `fn` + | help: visibility `pub` must come before `extern "C"`: `pub extern "C"` + +error: aborting due to previous error + From 8efd9cc30dd04cb4e58d9c0420f9ae88e5850f4e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 4 Jul 2023 17:28:57 +0300 Subject: [PATCH 04/18] resolve: Use `Interned` for `NameBinding` --- .../rustc_resolve/src/build_reduced_graph.rs | 14 ++-- compiler/rustc_resolve/src/diagnostics.rs | 22 +++--- .../src/effective_visibilities.rs | 18 ++--- compiler/rustc_resolve/src/ident.rs | 42 +++++------ compiler/rustc_resolve/src/imports.rs | 53 +++++++------ compiler/rustc_resolve/src/late.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 75 +++++++++---------- compiler/rustc_resolve/src/macros.rs | 4 +- 8 files changed, 106 insertions(+), 124 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 7277773334513..9af06f1a48a3c 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -9,7 +9,7 @@ use crate::def_collector::collect_definitions; use crate::imports::{Import, ImportKind}; use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; use crate::Namespace::{self, MacroNS, TypeNS, ValueNS}; -use crate::{errors, BindingKey, MacroData}; +use crate::{errors, BindingKey, MacroData, NameBindingData}; use crate::{Determinacy, ExternPreludeEntry, Finalize, Module, ModuleKind, ModuleOrUniformRoot}; use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PerNS, ResolutionError}; use crate::{Resolver, ResolverArenas, Segment, ToNameBinding, VisResolutionError}; @@ -38,8 +38,8 @@ type Res = def::Res; impl<'a, Id: Into> ToNameBinding<'a> for (Module<'a>, ty::Visibility, Span, LocalExpnId) { - fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { - arenas.alloc_name_binding(NameBinding { + fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a> { + arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Module(self.0), ambiguity: None, vis: self.1.to_def_id(), @@ -50,8 +50,8 @@ impl<'a, Id: Into> ToNameBinding<'a> } impl<'a, Id: Into> ToNameBinding<'a> for (Res, ty::Visibility, Span, LocalExpnId) { - fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { - arenas.alloc_name_binding(NameBinding { + fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a> { + arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Res(self.0), ambiguity: None, vis: self.1.to_def_id(), @@ -71,7 +71,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let binding = def.to_name_binding(self.arenas); let key = self.new_disambiguated_key(ident, ns); if let Err(old_binding) = self.try_define(parent, key, binding) { - self.report_conflict(parent, ident, ns, old_binding, &binding); + self.report_conflict(parent, ident, ns, old_binding, binding); } } @@ -996,7 +996,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { fn add_macro_use_binding( &mut self, name: Symbol, - binding: &'a NameBinding<'a>, + binding: NameBinding<'a>, span: Span, allow_shadowing: bool, ) { diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index d9e4974626d78..4db4108c6f42a 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -182,13 +182,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - pub(crate) fn report_conflict<'b>( + pub(crate) fn report_conflict( &mut self, parent: Module<'_>, ident: Ident, ns: Namespace, - new_binding: &NameBinding<'b>, - old_binding: &NameBinding<'b>, + new_binding: NameBinding<'a>, + old_binding: NameBinding<'a>, ) { // Error on the second of two conflicting names if old_binding.span.lo() > new_binding.span.lo() { @@ -262,7 +262,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // See https://github.com/rust-lang/rust/issues/32354 use NameBindingKind::Import; - let can_suggest = |binding: &NameBinding<'_>, import: &self::Import<'_>| { + let can_suggest = |binding: NameBinding<'_>, import: &self::Import<'_>| { !binding.span.is_dummy() && !matches!(import.kind, ImportKind::MacroUse | ImportKind::MacroExport) }; @@ -455,7 +455,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, finalize: Option, path: &[Segment], - second_binding: Option<&NameBinding<'_>>, + second_binding: Option>, ) { let Some(Finalize { node_id, root_span, .. }) = finalize else { return; @@ -1515,7 +1515,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { true } - fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: bool) -> String { + fn binding_description(&self, b: NameBinding<'_>, ident: Ident, from_prelude: bool) -> String { let res = b.res(); if b.span.is_dummy() || !self.tcx.sess.source_map().is_span_accessible(b.span) { // These already contain the "built-in" prefix or look bad with it. @@ -1555,7 +1555,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { err.span_label(ident.span, "ambiguous name"); err.note(format!("ambiguous because of {}", kind.descr())); - let mut could_refer_to = |b: &NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| { + let mut could_refer_to = |b: NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| { let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude); let note_msg = format!("`{ident}` could{also} refer to {what}"); @@ -1595,7 +1595,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// If the binding refers to a tuple struct constructor with fields, /// returns the span of its fields. - fn ctor_fields_span(&self, binding: &NameBinding<'_>) -> Option { + fn ctor_fields_span(&self, binding: NameBinding<'_>) -> Option { if let NameBindingKind::Res(Res::Def( DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id, @@ -1622,7 +1622,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr }; let import_descr = nonimport_descr.clone() + " import"; let get_descr = - |b: &NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr }; + |b: NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr }; // Print the primary message. let descr = get_descr(binding); @@ -1702,7 +1702,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { _ => None, }; - let first = ptr::eq(binding, first_binding); + let first = binding == first_binding; let msg = format!( "{and_refers_to}the {item} `{name}`{which} is defined here{dots}", and_refers_to = if first { "" } else { "...and refers to " }, @@ -1762,7 +1762,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { opt_ns: Option, // `None` indicates a module path in import parent_scope: &ParentScope<'a>, ribs: Option<&PerNS>>>, - ignore_binding: Option<&'a NameBinding<'a>>, + ignore_binding: Option>, module: Option>, failed_segment_idx: usize, ident: Ident, diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 4863c9f479015..eb210532f51df 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -5,7 +5,6 @@ use rustc_ast::visit::Visitor; use rustc_ast::Crate; use rustc_ast::EnumDef; use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::intern::Interned; use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_middle::middle::privacy::Level; @@ -13,12 +12,10 @@ use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility}; use rustc_middle::ty::Visibility; use std::mem; -type ImportId<'a> = Interned<'a, NameBinding<'a>>; - #[derive(Clone, Copy)] enum ParentId<'a> { Def(LocalDefId), - Import(ImportId<'a>), + Import(NameBinding<'a>), } impl ParentId<'_> { @@ -36,7 +33,7 @@ pub(crate) struct EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { /// While walking import chains we need to track effective visibilities per-binding, and def id /// keys in `Resolver::effective_visibilities` are not enough for that, because multiple /// bindings can correspond to a single def id in imports. So we keep a separate table. - import_effective_visibilities: EffectiveVisibilities>, + import_effective_visibilities: EffectiveVisibilities>, // It's possible to recalculate this at any point, but it's relatively expensive. current_private_vis: Visibility, changed: bool, @@ -47,7 +44,7 @@ impl Resolver<'_, '_> { self.get_nearest_non_block_module(def_id.to_def_id()).nearest_parent_mod().expect_local() } - fn private_vis_import(&mut self, binding: ImportId<'_>) -> Visibility { + fn private_vis_import(&mut self, binding: NameBinding<'_>) -> Visibility { let NameBindingKind::Import { import, .. } = binding.kind else { unreachable!() }; Visibility::Restricted( import @@ -75,7 +72,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { pub(crate) fn compute_effective_visibilities<'c>( r: &'r mut Resolver<'a, 'tcx>, krate: &'c Crate, - ) -> FxHashSet>> { + ) -> FxHashSet> { let mut visitor = EffectiveVisibilitiesVisitor { r, def_effective_visibilities: Default::default(), @@ -133,8 +130,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { // lint. For all bindings added to the table this way `is_ambiguity` returns true. let mut parent_id = ParentId::Def(module_id); while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind { - let binding_id = ImportId::new_unchecked(binding); - self.update_import(binding_id, parent_id); + self.update_import(binding, parent_id); if binding.ambiguity.is_some() { // Stop at the root ambiguity, further bindings in the chain should not @@ -143,7 +139,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { break; } - parent_id = ParentId::Import(binding_id); + parent_id = ParentId::Import(binding); binding = nested_binding; } @@ -192,7 +188,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { } } - fn update_import(&mut self, binding: ImportId<'a>, parent_id: ParentId<'a>) { + fn update_import(&mut self, binding: NameBinding<'a>, parent_id: ParentId<'a>) { let nominal_vis = binding.vis.expect_local(); let Some(cheap_private_vis) = self.may_update(nominal_vis, parent_id) else { return }; let inherited_eff_vis = self.effective_vis_or_private(parent_id); diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 36f01676e7e09..ba6f50ef1baed 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -284,7 +284,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { parent_scope: &ParentScope<'a>, finalize: Option, ribs: &[Rib<'a>], - ignore_binding: Option<&'a NameBinding<'a>>, + ignore_binding: Option>, ) -> Option> { assert!(ns == TypeNS || ns == ValueNS); let orig_ident = ident; @@ -378,8 +378,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { parent_scope: &ParentScope<'a>, finalize: Option, force: bool, - ignore_binding: Option<&'a NameBinding<'a>>, - ) -> Result<&'a NameBinding<'a>, Determinacy> { + ignore_binding: Option>, + ) -> Result, Determinacy> { bitflags::bitflags! { struct Flags: u8 { const MACRO_RULES = 1 << 0; @@ -415,7 +415,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // } // So we have to save the innermost solution and continue searching in outer scopes // to detect potential ambiguities. - let mut innermost_result: Option<(&NameBinding<'_>, Flags)> = None; + let mut innermost_result: Option<(NameBinding<'_>, Flags)> = None; let mut determinacy = Determinacy::Determined; // Go through all the scopes and try to resolve the name. @@ -717,7 +717,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ident: Ident, ns: Namespace, parent_scope: &ParentScope<'a>, - ) -> Result<&'a NameBinding<'a>, Determinacy> { + ) -> Result, Determinacy> { self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, None) .map_err(|(determinacy, _)| determinacy) } @@ -730,8 +730,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ns: Namespace, parent_scope: &ParentScope<'a>, finalize: Option, - ignore_binding: Option<&'a NameBinding<'a>>, - ) -> Result<&'a NameBinding<'a>, Determinacy> { + ignore_binding: Option>, + ) -> Result, Determinacy> { self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, finalize, ignore_binding) .map_err(|(determinacy, _)| determinacy) } @@ -744,8 +744,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ns: Namespace, parent_scope: &ParentScope<'a>, finalize: Option, - ignore_binding: Option<&'a NameBinding<'a>>, - ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> { + ignore_binding: Option>, + ) -> Result, (Determinacy, Weak)> { let tmp_parent_scope; let mut adjusted_parent_scope = parent_scope; match module { @@ -782,8 +782,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ns: Namespace, parent_scope: &ParentScope<'a>, finalize: Option, - ignore_binding: Option<&'a NameBinding<'a>>, - ) -> Result<&'a NameBinding<'a>, Determinacy> { + ignore_binding: Option>, + ) -> Result, Determinacy> { self.resolve_ident_in_module_unadjusted_ext( module, ident, @@ -809,8 +809,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { finalize: Option, // This binding should be ignored during in-module resolution, so that we don't get // "self-confirming" import resolutions during import validation and checking. - ignore_binding: Option<&'a NameBinding<'a>>, - ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> { + ignore_binding: Option>, + ) -> Result, (Determinacy, Weak)> { let module = match module { ModuleOrUniformRoot::Module(module) => module, ModuleOrUniformRoot::CrateRootAndExternPrelude => { @@ -873,13 +873,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // binding if it exists. What we really want here is having two separate scopes in // a module - one for non-globs and one for globs, but until that's done use this // hack to avoid inconsistent resolution ICEs during import validation. - let binding = - [resolution.binding, resolution.shadowed_glob].into_iter().find_map(|binding| { - match (binding, ignore_binding) { - (Some(binding), Some(ignored)) if ptr::eq(binding, ignored) => None, - _ => binding, - } - }); + let binding = [resolution.binding, resolution.shadowed_glob] + .into_iter() + .find_map(|binding| if binding == ignore_binding { None } else { binding }); if let Some(Finalize { path_span, report_private, .. }) = finalize { let Some(binding) = binding else { @@ -930,7 +926,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return Ok(binding); } - let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| { + let check_usable = |this: &mut Self, binding: NameBinding<'a>| { let usable = this.is_accessible_from(binding.vis, parent_scope.module); if usable { Ok(binding) } else { Err((Determined, Weak::No)) } }; @@ -1352,7 +1348,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { opt_ns: Option, // `None` indicates a module path in import parent_scope: &ParentScope<'a>, finalize: Option, - ignore_binding: Option<&'a NameBinding<'a>>, + ignore_binding: Option>, ) -> PathResult<'a> { self.resolve_path_with_ribs(path, opt_ns, parent_scope, finalize, None, ignore_binding) } @@ -1364,7 +1360,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { parent_scope: &ParentScope<'a>, finalize: Option, ribs: Option<&PerNS>>>, - ignore_binding: Option<&'a NameBinding<'a>>, + ignore_binding: Option>, ) -> PathResult<'a> { let mut module = None; let mut allow_super = true; diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 074f761c53baa..5f5b49d8564d7 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -12,7 +12,7 @@ use crate::{fluent_generated as fluent, Namespace::*}; use crate::{module_to_string, names_to_string, ImportSuggestion}; use crate::{AmbiguityKind, BindingKey, ModuleKind, ResolutionError, Resolver, Segment}; use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet}; -use crate::{NameBinding, NameBindingKind, PathResult}; +use crate::{NameBinding, NameBindingData, NameBindingKind, PathResult}; use rustc_ast::NodeId; use rustc_data_structures::fx::FxHashSet; @@ -48,9 +48,9 @@ pub(crate) enum ImportKind<'a> { /// `target` in `use prefix::source as target`. target: Ident, /// Bindings to which `source` refers to. - source_bindings: PerNS, Determinacy>>>, + source_bindings: PerNS, Determinacy>>>, /// Bindings introduced by `target`. - target_bindings: PerNS>>>, + target_bindings: PerNS>>>, /// `true` for `...::{self [as target]}` imports, `false` otherwise. type_ns_only: bool, /// Did this import result from a nested import? ie. `use foo::{bar, baz};` @@ -216,13 +216,13 @@ pub(crate) struct NameResolution<'a> { /// Imports are arena-allocated, so it's ok to use pointers as keys. pub single_imports: FxHashSet>>, /// The least shadowable known binding for this name, or None if there are no known bindings. - pub binding: Option<&'a NameBinding<'a>>, - pub shadowed_glob: Option<&'a NameBinding<'a>>, + pub binding: Option>, + pub shadowed_glob: Option>, } impl<'a> NameResolution<'a> { /// Returns the binding for the name if it is known or None if it not known. - pub(crate) fn binding(&self) -> Option<&'a NameBinding<'a>> { + pub(crate) fn binding(&self) -> Option> { self.binding.and_then(|binding| { if !binding.is_glob_import() || self.single_imports.is_empty() { Some(binding) @@ -250,7 +250,7 @@ struct UnresolvedImportError { // Reexports of the form `pub use foo as bar;` where `foo` is `extern crate foo;` // are permitted for backward-compatibility under a deprecation lint. -fn pub_use_of_private_extern_crate_hack(import: &Import<'_>, binding: &NameBinding<'_>) -> bool { +fn pub_use_of_private_extern_crate_hack(import: &Import<'_>, binding: NameBinding<'_>) -> bool { match (&import.kind, &binding.kind) { ( ImportKind::Single { .. }, @@ -268,9 +268,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// return the corresponding binding defined by the import. pub(crate) fn import( &self, - binding: &'a NameBinding<'a>, + binding: NameBinding<'a>, import: &'a Import<'a>, - ) -> &'a NameBinding<'a> { + ) -> NameBinding<'a> { let import_vis = import.expect_vis().to_def_id(); let vis = if binding.vis.is_at_least(import_vis, self.tcx) || pub_use_of_private_extern_crate_hack(import, binding) @@ -288,7 +288,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - self.arenas.alloc_name_binding(NameBinding { + self.arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Import { binding, import, used: Cell::new(false) }, ambiguity: None, span: import.span, @@ -302,8 +302,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, module: Module<'a>, key: BindingKey, - binding: &'a NameBinding<'a>, - ) -> Result<(), &'a NameBinding<'a>> { + binding: NameBinding<'a>, + ) -> Result<(), NameBinding<'a>> { let res = binding.res(); self.check_reserved_macro_name(key.ident, res); self.set_binding_parent_module(binding, module); @@ -372,12 +372,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn ambiguity( &self, kind: AmbiguityKind, - primary_binding: &'a NameBinding<'a>, - secondary_binding: &'a NameBinding<'a>, - ) -> &'a NameBinding<'a> { - self.arenas.alloc_name_binding(NameBinding { + primary_binding: NameBinding<'a>, + secondary_binding: NameBinding<'a>, + ) -> NameBinding<'a> { + self.arenas.alloc_name_binding(NameBindingData { ambiguity: Some((secondary_binding, kind)), - ..primary_binding.clone() + ..(*primary_binding).clone() }) } @@ -395,13 +395,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let t = f(self, resolution); - match resolution.binding() { - _ if old_binding.is_some() => return t, - None => return t, - Some(binding) => match old_binding { - Some(old_binding) if ptr::eq(old_binding, binding) => return t, - _ => (binding, t), - }, + if old_binding.is_none() && let Some(binding) = resolution.binding() { + (binding, t) + } else { + return t; } }; @@ -546,7 +543,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn check_hidden_glob_reexports( &mut self, - exported_ambiguities: FxHashSet>>, + exported_ambiguities: FxHashSet>, ) { for module in self.arenas.local_modules().iter() { for (key, resolution) in self.resolutions(module).borrow().iter() { @@ -556,7 +553,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let NameBindingKind::Import { import, .. } = binding.kind && let Some((amb_binding, _)) = binding.ambiguity && binding.res() != Res::Err - && exported_ambiguities.contains(&Interned::new_unchecked(binding)) + && exported_ambiguities.contains(&binding) { self.lint_buffer.buffer_lint_with_diagnostic( AMBIGUOUS_GLOB_REEXPORTS, @@ -1243,8 +1240,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, ident: Ident, import: &'a Import<'a>, - source_bindings: &PerNS, Determinacy>>>, - target_bindings: &PerNS>>>, + source_bindings: &PerNS, Determinacy>>>, + target_bindings: &PerNS>>>, target: Ident, ) { // This function is only called for single imports. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index bca95ce54ad33..735a499ff68dd 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1284,7 +1284,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ident: Ident, ns: Namespace, finalize: Option, - ignore_binding: Option<&'a NameBinding<'a>>, + ignore_binding: Option>, ) -> Option> { self.r.resolve_ident_in_lexical_scope( ident, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index cc4cb9fa30cd9..8fefbe8177e5b 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -352,7 +352,7 @@ impl<'a> From<&'a ast::PathSegment> for Segment { /// forward. #[derive(Debug)] enum LexicalScopeBinding<'a> { - Item(&'a NameBinding<'a>), + Item(NameBinding<'a>), Res(Res), } @@ -522,7 +522,7 @@ struct ModuleData<'a> { globs: RefCell>>, /// Used to memoize the traits in this module for faster searches through all traits in scope. - traits: RefCell)]>>>, + traits: RefCell)]>>>, /// Span of the module itself. Used for error reporting. span: Span, @@ -562,7 +562,7 @@ impl<'a> ModuleData<'a> { fn for_each_child<'tcx, R, F>(&'a self, resolver: &mut R, mut f: F) where R: AsMut>, - F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>), + F: FnMut(&mut R, Ident, Namespace, NameBinding<'a>), { for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() { if let Some(binding) = name_resolution.borrow().binding { @@ -657,20 +657,22 @@ impl<'a> fmt::Debug for ModuleData<'a> { /// Records a possibly-private value, type, or module definition. #[derive(Clone, Debug)] -struct NameBinding<'a> { +struct NameBindingData<'a> { kind: NameBindingKind<'a>, - ambiguity: Option<(&'a NameBinding<'a>, AmbiguityKind)>, + ambiguity: Option<(NameBinding<'a>, AmbiguityKind)>, expansion: LocalExpnId, span: Span, vis: ty::Visibility, } +type NameBinding<'a> = Interned<'a, NameBindingData<'a>>; + trait ToNameBinding<'a> { - fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'a>; + fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a>; } -impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> { - fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> &'a NameBinding<'a> { +impl<'a> ToNameBinding<'a> for NameBinding<'a> { + fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> NameBinding<'a> { self } } @@ -679,7 +681,7 @@ impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> { enum NameBindingKind<'a> { Res(Res), Module(Module<'a>), - Import { binding: &'a NameBinding<'a>, import: &'a Import<'a>, used: Cell }, + Import { binding: NameBinding<'a>, import: &'a Import<'a>, used: Cell }, } impl<'a> NameBindingKind<'a> { @@ -692,7 +694,7 @@ impl<'a> NameBindingKind<'a> { #[derive(Debug)] struct PrivacyError<'a> { ident: Ident, - binding: &'a NameBinding<'a>, + binding: NameBinding<'a>, dedup_span: Span, outermost_res: Option<(Res, Ident)>, parent_scope: ParentScope<'a>, @@ -761,13 +763,13 @@ enum AmbiguityErrorMisc { struct AmbiguityError<'a> { kind: AmbiguityKind, ident: Ident, - b1: &'a NameBinding<'a>, - b2: &'a NameBinding<'a>, + b1: NameBinding<'a>, + b2: NameBinding<'a>, misc1: AmbiguityErrorMisc, misc2: AmbiguityErrorMisc, } -impl<'a> NameBinding<'a> { +impl<'a> NameBindingData<'a> { fn module(&self) -> Option> { match self.kind { NameBindingKind::Module(module) => Some(module), @@ -855,7 +857,7 @@ impl<'a> NameBinding<'a> { fn may_appear_after( &self, invoc_parent_expansion: LocalExpnId, - binding: &NameBinding<'_>, + binding: NameBinding<'_>, ) -> bool { // self > max(invoc, binding) => !(self <= invoc || self <= binding) // Expansions are partially ordered, so "may appear after" is an inversion of @@ -872,7 +874,7 @@ impl<'a> NameBinding<'a> { #[derive(Default, Clone)] struct ExternPreludeEntry<'a> { - extern_crate_item: Option<&'a NameBinding<'a>>, + extern_crate_item: Option>, introduced_by_item: bool, } @@ -962,7 +964,7 @@ pub struct Resolver<'a, 'tcx> { /// language items. empty_module: Module<'a>, module_map: FxHashMap>, - binding_parent_modules: FxHashMap>, Module<'a>>, + binding_parent_modules: FxHashMap, Module<'a>>, underscore_disambiguator: u32, @@ -984,7 +986,7 @@ pub struct Resolver<'a, 'tcx> { macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>, arenas: &'a ResolverArenas<'a>, - dummy_binding: &'a NameBinding<'a>, + dummy_binding: NameBinding<'a>, used_extern_options: FxHashSet, macro_names: FxHashSet, @@ -993,7 +995,7 @@ pub struct Resolver<'a, 'tcx> { /// the surface (`macro` items in libcore), but are actually attributes or derives. builtin_macro_kinds: FxHashMap, registered_tools: &'tcx RegisteredTools, - macro_use_prelude: FxHashMap>, + macro_use_prelude: FxHashMap>, macro_map: FxHashMap, dummy_ext_bang: Lrc, dummy_ext_derive: Lrc, @@ -1005,7 +1007,7 @@ pub struct Resolver<'a, 'tcx> { proc_macro_stubs: FxHashSet, /// Traces collected during macro resolution and validated when it's complete. single_segment_macro_resolutions: - Vec<(Ident, MacroKind, ParentScope<'a>, Option<&'a NameBinding<'a>>)>, + Vec<(Ident, MacroKind, ParentScope<'a>, Option>)>, multi_segment_macro_resolutions: Vec<(Vec, Span, MacroKind, ParentScope<'a>, Option)>, builtin_attrs: Vec<(Ident, ParentScope<'a>)>, @@ -1115,8 +1117,8 @@ impl<'a> ResolverArenas<'a> { fn local_modules(&'a self) -> std::cell::Ref<'a, Vec>> { self.local_modules.borrow() } - fn alloc_name_binding(&'a self, name_binding: NameBinding<'a>) -> &'a NameBinding<'a> { - self.dropless.alloc(name_binding) + fn alloc_name_binding(&'a self, name_binding: NameBindingData<'a>) -> NameBinding<'a> { + Interned::new_unchecked(self.dropless.alloc(name_binding)) } fn alloc_import(&'a self, import: Import<'a>) -> &'a Import<'_> { self.imports.alloc(import) @@ -1314,7 +1316,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { macro_expanded_macro_export_errors: BTreeSet::new(), arenas, - dummy_binding: arenas.alloc_name_binding(NameBinding { + dummy_binding: arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Res(Res::Err), ambiguity: None, expansion: LocalExpnId::ROOT, @@ -1679,12 +1681,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { false } - fn record_use( - &mut self, - ident: Ident, - used_binding: &'a NameBinding<'a>, - is_lexical_scope: bool, - ) { + fn record_use(&mut self, ident: Ident, used_binding: NameBinding<'a>, is_lexical_scope: bool) { if let Some((b2, kind)) = used_binding.ambiguity { let ambiguity_error = AmbiguityError { kind, @@ -1704,10 +1701,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // but not introduce it, as used if they are accessed from lexical scope. if is_lexical_scope { if let Some(entry) = self.extern_prelude.get(&ident.normalize_to_macros_2_0()) { - if let Some(crate_item) = entry.extern_crate_item { - if ptr::eq(used_binding, crate_item) && !entry.introduced_by_item { - return; - } + if !entry.introduced_by_item && entry.extern_crate_item == Some(used_binding) { + return; } } } @@ -1831,10 +1826,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { vis.is_accessible_from(module.nearest_parent_mod(), self.tcx) } - fn set_binding_parent_module(&mut self, binding: &'a NameBinding<'a>, module: Module<'a>) { - if let Some(old_module) = - self.binding_parent_modules.insert(Interned::new_unchecked(binding), module) - { + fn set_binding_parent_module(&mut self, binding: NameBinding<'a>, module: Module<'a>) { + if let Some(old_module) = self.binding_parent_modules.insert(binding, module) { if !ptr::eq(module, old_module) { span_bug!(binding.span, "parent module is reset for binding"); } @@ -1843,15 +1836,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn disambiguate_macro_rules_vs_modularized( &self, - macro_rules: &'a NameBinding<'a>, - modularized: &'a NameBinding<'a>, + macro_rules: NameBinding<'a>, + modularized: NameBinding<'a>, ) -> bool { // Some non-controversial subset of ambiguities "modularized macro name" vs "macro_rules" // is disambiguated to mitigate regressions from macro modularization. // Scoping for `macro_rules` behaves like scoping for `let` at module level, in general. match ( - self.binding_parent_modules.get(&Interned::new_unchecked(macro_rules)), - self.binding_parent_modules.get(&Interned::new_unchecked(modularized)), + self.binding_parent_modules.get(¯o_rules), + self.binding_parent_modules.get(&modularized), ) { (Some(macro_rules), Some(modularized)) => { macro_rules.nearest_parent_mod() == modularized.nearest_parent_mod() @@ -1861,7 +1854,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option<&'a NameBinding<'a>> { + fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option> { if ident.is_path_segment_keyword() { // Make sure `self`, `super` etc produce an error when passed to here. return None; diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index d33e8d40b6383..d16b7902f6069 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -42,7 +42,7 @@ type Res = def::Res; /// Not modularized, can shadow previous `macro_rules` bindings, etc. #[derive(Debug)] pub(crate) struct MacroRulesBinding<'a> { - pub(crate) binding: &'a NameBinding<'a>, + pub(crate) binding: NameBinding<'a>, /// `macro_rules` scope into which the `macro_rules` item was planted. pub(crate) parent_macro_rules_scope: MacroRulesScopeRef<'a>, pub(crate) ident: Ident, @@ -870,7 +870,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn prohibit_imported_non_macro_attrs( &self, - binding: Option<&'a NameBinding<'a>>, + binding: Option>, res: Option, span: Span, ) { From 4abdaeb67eb3aa85941cee4928b75dbcbd120148 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 4 Jul 2023 18:51:35 +0300 Subject: [PATCH 05/18] resolve: Use `Interned` for `Import` --- .../rustc_resolve/src/build_reduced_graph.rs | 12 ++--- compiler/rustc_resolve/src/diagnostics.rs | 24 ++++----- compiler/rustc_resolve/src/ident.rs | 11 ++--- compiler/rustc_resolve/src/imports.rs | 49 ++++++++----------- compiler/rustc_resolve/src/lib.rs | 33 ++++++------- 5 files changed, 58 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 9af06f1a48a3c..fdf1e281b0bd4 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -6,7 +6,7 @@ //! Imports are also considered items and placed into modules here, but not resolved yet. use crate::def_collector::collect_definitions; -use crate::imports::{Import, ImportKind}; +use crate::imports::{ImportData, ImportKind}; use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; use crate::Namespace::{self, MacroNS, TypeNS, ValueNS}; use crate::{errors, BindingKey, MacroData, NameBindingData}; @@ -354,7 +354,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { vis: ty::Visibility, ) { let current_module = self.parent_scope.module; - let import = self.r.arenas.alloc_import(Import { + let import = self.r.arenas.alloc_import(ImportData { kind, parent_scope: self.parent_scope, module_path, @@ -378,7 +378,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { if !type_ns_only || ns == TypeNS { let key = BindingKey::new(target, ns); let mut resolution = this.resolution(current_module, key).borrow_mut(); - resolution.add_single_import(import); + resolution.single_imports.insert(import); } }); } @@ -848,7 +848,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { (used, Some(ModuleOrUniformRoot::Module(module)), binding) }) .unwrap_or((true, None, self.r.dummy_binding)); - let import = self.r.arenas.alloc_import(Import { + let import = self.r.arenas.alloc_import(ImportData { kind: ImportKind::ExternCrate { source: orig_name, target: ident, id: item.id }, root_id: item.id, parent_scope: self.parent_scope, @@ -1058,7 +1058,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } let macro_use_import = |this: &Self, span| { - this.r.arenas.alloc_import(Import { + this.r.arenas.alloc_import(ImportData { kind: ImportKind::MacroUse, root_id: item.id, parent_scope: this.parent_scope, @@ -1228,7 +1228,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.r.set_binding_parent_module(binding, parent_scope.module); self.r.all_macro_rules.insert(ident.name, res); if is_macro_export { - let import = self.r.arenas.alloc_import(Import { + let import = self.r.arenas.alloc_import(ImportData { kind: ImportKind::MacroExport, root_id: item.id, parent_scope: self.parent_scope, diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 4db4108c6f42a..9c1d425146579 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -262,7 +262,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // See https://github.com/rust-lang/rust/issues/32354 use NameBindingKind::Import; - let can_suggest = |binding: NameBinding<'_>, import: &self::Import<'_>| { + let can_suggest = |binding: NameBinding<'_>, import: self::Import<'_>| { !binding.span.is_dummy() && !matches!(import.kind, ImportKind::MacroUse | ImportKind::MacroExport) }; @@ -272,22 +272,22 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { (Import { import: new, .. }, Import { import: old, .. }) if { (new.has_attributes || old.has_attributes) - && can_suggest(old_binding, old) - && can_suggest(new_binding, new) + && can_suggest(old_binding, *old) + && can_suggest(new_binding, *new) } => { if old.has_attributes { - Some((new, new_binding.span, true)) + Some((*new, new_binding.span, true)) } else { - Some((old, old_binding.span, true)) + Some((*old, old_binding.span, true)) } } // Otherwise prioritize the new binding. - (Import { import, .. }, other) if can_suggest(new_binding, import) => { - Some((import, new_binding.span, other.is_import())) + (Import { import, .. }, other) if can_suggest(new_binding, *import) => { + Some((*import, new_binding.span, other.is_import())) } - (other, Import { import, .. }) if can_suggest(old_binding, import) => { - Some((import, old_binding.span, other.is_import())) + (other, Import { import, .. }) if can_suggest(old_binding, *import) => { + Some((*import, old_binding.span, other.is_import())) } _ => None, }; @@ -341,7 +341,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &self, err: &mut Diagnostic, name: Symbol, - import: &Import<'_>, + import: Import<'_>, binding_span: Span, ) { let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() { @@ -413,7 +413,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn add_suggestion_for_duplicate_nested_use( &self, err: &mut Diagnostic, - import: &Import<'_>, + import: Import<'_>, binding_span: Span, ) { assert!(import.is_nested()); @@ -2114,7 +2114,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// ``` pub(crate) fn check_for_module_export_macro( &mut self, - import: &'a Import<'a>, + import: Import<'a>, module: ModuleOrUniformRoot<'a>, ident: Ident, ) -> Option<(Option, Option)> { diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index ba6f50ef1baed..40eee48e475c4 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -20,7 +20,7 @@ use crate::late::{ use crate::macros::{sub_namespace_match, MacroRulesScope}; use crate::BindingKey; use crate::{errors, AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy, Finalize}; -use crate::{Import, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot}; +use crate::{ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot}; use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res}; use crate::{ResolutionError, Resolver, Scope, ScopeSet, Segment, ToNameBinding, Weak}; @@ -913,11 +913,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if !restricted_shadowing && binding.expansion != LocalExpnId::ROOT { - if let NameBindingKind::Import { - import: Import { kind: ImportKind::MacroExport, .. }, - .. - } = binding.kind - { + if let NameBindingKind::Import { import, .. } = binding.kind + && matches!(import.kind, ImportKind::MacroExport) { self.macro_expanded_macro_export_errors.insert((path_span, binding.span)); } } @@ -951,7 +948,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if let Some(ignored) = ignore_binding && let NameBindingKind::Import { import, .. } = ignored.kind && - ptr::eq(import, &**single_import) { + import == *single_import { // Ignore not just the binding itself, but if it has a shadowed_glob, // ignore that, too, because this loop is supposed to only process // named imports. diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 5f5b49d8564d7..fa8c15abc4b2e 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -135,7 +135,7 @@ impl<'a> std::fmt::Debug for ImportKind<'a> { /// One import. #[derive(Debug, Clone)] -pub(crate) struct Import<'a> { +pub(crate) struct ImportData<'a> { pub kind: ImportKind<'a>, /// Node ID of the "root" use item -- this is always the same as `ImportKind`'s `id` @@ -172,7 +172,9 @@ pub(crate) struct Import<'a> { pub used: Cell, } -impl<'a> Import<'a> { +pub(crate) type Import<'a> = Interned<'a, ImportData<'a>>; + +impl<'a> ImportData<'a> { pub(crate) fn is_glob(&self) -> bool { matches!(self.kind, ImportKind::Glob { .. }) } @@ -214,7 +216,7 @@ impl<'a> Import<'a> { pub(crate) struct NameResolution<'a> { /// Single imports that may define the name in the namespace. /// Imports are arena-allocated, so it's ok to use pointers as keys. - pub single_imports: FxHashSet>>, + pub single_imports: FxHashSet>, /// The least shadowable known binding for this name, or None if there are no known bindings. pub binding: Option>, pub shadowed_glob: Option>, @@ -231,10 +233,6 @@ impl<'a> NameResolution<'a> { } }) } - - pub(crate) fn add_single_import(&mut self, import: &'a Import<'a>) { - self.single_imports.insert(Interned::new_unchecked(import)); - } } /// An error that may be transformed into a diagnostic later. Used to combine multiple unresolved @@ -250,15 +248,12 @@ struct UnresolvedImportError { // Reexports of the form `pub use foo as bar;` where `foo` is `extern crate foo;` // are permitted for backward-compatibility under a deprecation lint. -fn pub_use_of_private_extern_crate_hack(import: &Import<'_>, binding: NameBinding<'_>) -> bool { +fn pub_use_of_private_extern_crate_hack(import: Import<'_>, binding: NameBinding<'_>) -> bool { match (&import.kind, &binding.kind) { - ( - ImportKind::Single { .. }, - NameBindingKind::Import { - import: Import { kind: ImportKind::ExternCrate { .. }, .. }, - .. - }, - ) => import.expect_vis().is_public(), + (ImportKind::Single { .. }, NameBindingKind::Import { import: binding_import, .. }) => { + matches!(binding_import.kind, ImportKind::ExternCrate { .. }) + && import.expect_vis().is_public() + } _ => false, } } @@ -266,11 +261,7 @@ fn pub_use_of_private_extern_crate_hack(import: &Import<'_>, binding: NameBindin impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Given a binding and an import that resolves to it, /// return the corresponding binding defined by the import. - pub(crate) fn import( - &self, - binding: NameBinding<'a>, - import: &'a Import<'a>, - ) -> NameBinding<'a> { + pub(crate) fn import(&self, binding: NameBinding<'a>, import: Import<'a>) -> NameBinding<'a> { let import_vis = import.expect_vis().to_def_id(); let vis = if binding.vis.is_at_least(import_vis, self.tcx) || pub_use_of_private_extern_crate_hack(import, binding) @@ -411,7 +402,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None => continue, }; if self.is_accessible_from(binding.vis, scope) { - let imported_binding = self.import(binding, import); + let imported_binding = self.import(binding, *import); let key = BindingKey { ident, ..key }; let _ = self.try_define(import.parent_scope.module, key, imported_binding); } @@ -422,7 +413,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed // or indeterminate resolution, also mark such failed imports as used to avoid duplicate diagnostics. - fn import_dummy_binding(&mut self, import: &'a Import<'a>, is_indeterminate: bool) { + fn import_dummy_binding(&mut self, import: Import<'a>, is_indeterminate: bool) { if let ImportKind::Single { target, ref target_bindings, .. } = import.kind { if !(is_indeterminate || target_bindings.iter().all(|binding| binding.get().is_none())) { @@ -460,7 +451,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { prev_indeterminate_count = indeterminate_count; indeterminate_count = 0; for import in mem::take(&mut self.indeterminate_imports) { - let import_indeterminate_count = self.resolve_import(&import); + let import_indeterminate_count = self.resolve_import(import); indeterminate_count += import_indeterminate_count; match import_indeterminate_count { 0 => self.determined_imports.push(import), @@ -609,7 +600,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn throw_unresolved_import_error(&mut self, errors: Vec<(&Import<'_>, UnresolvedImportError)>) { + fn throw_unresolved_import_error(&mut self, errors: Vec<(Import<'_>, UnresolvedImportError)>) { if errors.is_empty() { return; } @@ -701,7 +692,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// /// Meanwhile, if resolve successful, the resolved bindings are written /// into the module. - fn resolve_import(&mut self, import: &'a Import<'a>) -> usize { + fn resolve_import(&mut self, import: Import<'a>) -> usize { debug!( "(resolving import for module) resolving import `{}::...` in `{}`", Segment::names_to_string(&import.module_path), @@ -781,7 +772,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } let key = BindingKey::new(target, ns); this.update_resolution(parent, key, |_, resolution| { - resolution.single_imports.remove(&Interned::new_unchecked(import)); + resolution.single_imports.remove(&import); }); } } @@ -795,7 +786,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// /// Optionally returns an unresolved import error. This error is buffered and used to /// consolidate multiple unresolved import errors into a single diagnostic. - fn finalize_import(&mut self, import: &'a Import<'a>) -> Option { + fn finalize_import(&mut self, import: Import<'a>) -> Option { let orig_vis = import.vis.take(); let ignore_binding = match &import.kind { ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(), @@ -1239,7 +1230,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn check_for_redundant_imports( &mut self, ident: Ident, - import: &'a Import<'a>, + import: Import<'a>, source_bindings: &PerNS, Determinacy>>>, target_bindings: &PerNS>>>, target: Ident, @@ -1302,7 +1293,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn resolve_glob_import(&mut self, import: &'a Import<'a>) { + fn resolve_glob_import(&mut self, import: Import<'a>) { // This function is only called for glob imports. let ImportKind::Glob { id, is_prelude, .. } = import.kind else { unreachable!() }; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 8fefbe8177e5b..8ee0c715a0ea5 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -64,7 +64,7 @@ use std::collections::BTreeSet; use std::{fmt, ptr}; use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion}; -use imports::{Import, ImportKind, NameResolution}; +use imports::{Import, ImportData, ImportKind, NameResolution}; use late::{HasGenericParams, PathSource, PatternSource}; use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; @@ -518,8 +518,8 @@ struct ModuleData<'a> { /// Whether `#[no_implicit_prelude]` is active. no_implicit_prelude: bool, - glob_importers: RefCell>>, - globs: RefCell>>, + glob_importers: RefCell>>, + globs: RefCell>>, /// Used to memoize the traits in this module for faster searches through all traits in scope. traits: RefCell)]>>>, @@ -681,7 +681,7 @@ impl<'a> ToNameBinding<'a> for NameBinding<'a> { enum NameBindingKind<'a> { Res(Res), Module(Module<'a>), - Import { binding: NameBinding<'a>, import: &'a Import<'a>, used: Cell }, + Import { binding: NameBinding<'a>, import: Import<'a>, used: Cell }, } impl<'a> NameBindingKind<'a> { @@ -807,10 +807,9 @@ impl<'a> NameBindingData<'a> { fn is_extern_crate(&self) -> bool { match self.kind { - NameBindingKind::Import { - import: &Import { kind: ImportKind::ExternCrate { .. }, .. }, - .. - } => true, + NameBindingKind::Import { import, .. } => { + matches!(import.kind, ImportKind::ExternCrate { .. }) + } NameBindingKind::Module(&ModuleData { kind: ModuleKind::Def(DefKind::Mod, def_id, _), .. @@ -919,10 +918,10 @@ pub struct Resolver<'a, 'tcx> { field_visibility_spans: FxHashMap>, /// All imports known to succeed or fail. - determined_imports: Vec<&'a Import<'a>>, + determined_imports: Vec>, /// All non-determined imports. - indeterminate_imports: Vec<&'a Import<'a>>, + indeterminate_imports: Vec>, // Spans for local variables found during pattern resolution. // Used for suggestions during error reporting. @@ -1032,7 +1031,7 @@ pub struct Resolver<'a, 'tcx> { /// Avoid duplicated errors for "name already defined". name_already_seen: FxHashMap, - potentially_unused_imports: Vec<&'a Import<'a>>, + potentially_unused_imports: Vec>, /// Table for mapping struct IDs into struct constructor IDs, /// it's not used during normal resolution, only for better error reporting. @@ -1087,7 +1086,7 @@ pub struct Resolver<'a, 'tcx> { pub struct ResolverArenas<'a> { modules: TypedArena>, local_modules: RefCell>>, - imports: TypedArena>, + imports: TypedArena>, name_resolutions: TypedArena>>, ast_paths: TypedArena, dropless: DroplessArena, @@ -1120,8 +1119,8 @@ impl<'a> ResolverArenas<'a> { fn alloc_name_binding(&'a self, name_binding: NameBindingData<'a>) -> NameBinding<'a> { Interned::new_unchecked(self.dropless.alloc(name_binding)) } - fn alloc_import(&'a self, import: Import<'a>) -> &'a Import<'_> { - self.imports.alloc(import) + fn alloc_import(&'a self, import: ImportData<'a>) -> Import<'a> { + Interned::new_unchecked(self.imports.alloc(import)) } fn alloc_name_resolution(&'a self) -> &'a RefCell> { self.name_resolutions.alloc(Default::default()) @@ -1626,7 +1625,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.maybe_unused_trait_imports.insert(def_id); import_ids.push(def_id); } - self.add_to_glob_map(&import, trait_name); + self.add_to_glob_map(*import, trait_name); kind = &binding.kind; } import_ids @@ -1711,13 +1710,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(id) = import.id() { self.used_imports.insert(id); } - self.add_to_glob_map(&import, ident); + self.add_to_glob_map(import, ident); self.record_use(ident, binding, false); } } #[inline] - fn add_to_glob_map(&mut self, import: &Import<'_>, ident: Ident) { + fn add_to_glob_map(&mut self, import: Import<'_>, ident: Ident) { if let ImportKind::Glob { id, .. } = import.kind { let def_id = self.local_def_id(id); self.glob_map.entry(def_id).or_default().insert(ident.name); From c1f412f9a93cee5bfd4c4cbdf0e0cb78fc51da2c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 4 Jul 2023 20:00:42 +0300 Subject: [PATCH 06/18] resolve: Use `Interned` for `Module` --- .../rustc_resolve/src/build_reduced_graph.rs | 7 +- compiler/rustc_resolve/src/diagnostics.rs | 15 ++-- compiler/rustc_resolve/src/ident.rs | 4 +- compiler/rustc_resolve/src/imports.rs | 12 +-- compiler/rustc_resolve/src/late.rs | 2 +- .../rustc_resolve/src/late/diagnostics.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 82 +++++++++---------- 7 files changed, 59 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index fdf1e281b0bd4..e6ceedddfa1be 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -31,7 +31,6 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use std::cell::Cell; -use std::ptr; type Res = def::Res; @@ -142,8 +141,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Some(def_id) => self.macro_def_scope(def_id), None => expn_id .as_local() - .and_then(|expn_id| self.ast_transform_scopes.get(&expn_id)) - .unwrap_or(&self.graph_root), + .and_then(|expn_id| self.ast_transform_scopes.get(&expn_id).copied()) + .unwrap_or(self.graph_root), } } @@ -864,7 +863,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { }); self.r.potentially_unused_imports.push(import); let imported_binding = self.r.import(binding, import); - if ptr::eq(parent, self.r.graph_root) { + if parent == self.r.graph_root { if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) { if expansion != LocalExpnId::ROOT && orig_name.is_some() diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 9c1d425146579..d3dcdfa427542 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1,5 +1,3 @@ -use std::ptr; - use rustc_ast::expand::StrippedCfgItem; use rustc_ast::ptr::P; use rustc_ast::visit::{self, Visitor}; @@ -1198,7 +1196,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // avoid suggesting anything with a hygienic name if ident.name == lookup_ident.name && ns == namespace - && !ptr::eq(in_module, parent_scope.module) + && in_module != parent_scope.module && !ident.span.normalize_to_macros_2_0().from_expansion() { let res = name_binding.res(); @@ -1732,7 +1730,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn find_similarly_named_module_or_crate( &mut self, ident: Symbol, - current_module: &Module<'a>, + current_module: Module<'a>, ) -> Option { let mut candidates = self .extern_prelude @@ -1742,7 +1740,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.module_map .iter() .filter(|(_, module)| { - current_module.is_ancestor_of(module) && !ptr::eq(current_module, *module) + current_module.is_ancestor_of(**module) && current_module != **module }) .flat_map(|(_, module)| module.kind.name()), ) @@ -1945,7 +1943,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } suggestion = suggestion.or_else(|| { - self.find_similarly_named_module_or_crate(ident.name, &parent_scope.module).map( + self.find_similarly_named_module_or_crate(ident.name, parent_scope.module).map( |sugg| { ( vec![(ident.span, sugg.to_string())], @@ -2126,9 +2124,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { crate_module = parent; } - if ModuleOrUniformRoot::same_def(ModuleOrUniformRoot::Module(crate_module), module) { - // Don't make a suggestion if the import was already from the root of the - // crate. + if module == ModuleOrUniformRoot::Module(crate_module) { + // Don't make a suggestion if the import was already from the root of the crate. return None; } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 40eee48e475c4..520fab1f0c837 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -11,8 +11,6 @@ use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContex use rustc_span::symbol::{kw, Ident}; use rustc_span::{Span, DUMMY_SP}; -use std::ptr; - use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst}; use crate::late::{ ConstantHasGenerics, HasGenericParams, NoConstantGenericsReason, PathSource, Rib, RibKind, @@ -538,7 +536,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ), ); } - let misc_flags = if ptr::eq(module, this.graph_root) { + let misc_flags = if module == this.graph_root { Flags::MISC_SUGGEST_CRATE } else if module.is_normal() { Flags::MISC_SUGGEST_SELF diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index fa8c15abc4b2e..036fbf2dbf0af 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -35,7 +35,7 @@ use rustc_span::Span; use smallvec::SmallVec; use std::cell::Cell; -use std::{mem, ptr}; +use std::mem; type Res = def::Res; @@ -463,7 +463,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn finalize_imports(&mut self) { for module in self.arenas.local_modules().iter() { - self.finalize_resolutions_in(module); + self.finalize_resolutions_in(*module); } let mut seen_spans = FxHashSet::default(); @@ -537,7 +537,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { exported_ambiguities: FxHashSet>, ) { for module in self.arenas.local_modules().iter() { - for (key, resolution) in self.resolutions(module).borrow().iter() { + for (key, resolution) in self.resolutions(*module).borrow().iter() { let resolution = resolution.borrow(); if let Some(binding) = resolution.binding { @@ -812,7 +812,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { PathResult::Module(module) => { // Consistency checks, analogous to `finalize_macro_resolutions`. if let Some(initial_module) = import.imported_module.get() { - if !ModuleOrUniformRoot::same_def(module, initial_module) && no_ambiguity { + if module != initial_module && no_ambiguity { span_bug!(import.span, "inconsistent resolution for an import"); } } else if self.privacy_errors.is_empty() { @@ -914,7 +914,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if let ModuleOrUniformRoot::Module(module) = module { - if ptr::eq(module, import.parent_scope.module) { + if module == import.parent_scope.module { // Importing a module into itself is not allowed. return Some(UnresolvedImportError { span: import.span, @@ -1307,7 +1307,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if module.is_trait() { self.tcx.sess.create_err(ItemsInTraitsAreNotImportable { span: import.span }).emit(); return; - } else if ptr::eq(module, import.parent_scope.module) { + } else if module == import.parent_scope.module { return; } else if is_prelude { self.prelude = Some(module); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 735a499ff68dd..90cb312edd203 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2972,7 +2972,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { F: FnOnce(Ident, String, Option) -> ResolutionError<'a>, { // If there is a TraitRef in scope for an impl, then the method must be in the trait. - let Some((module, _)) = &self.current_trait_ref else { return; }; + let Some((module, _)) = self.current_trait_ref else { return; }; ident.span.normalize_to_macros_2_0_and_adjust(module.expansion); let key = BindingKey::new(ident, ns); let mut binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 9fec7cc3defb3..c0e3f1aaf01f0 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1593,7 +1593,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { return None; } - let resolutions = self.r.resolutions(module); + let resolutions = self.r.resolutions(*module); let targets = resolutions .borrow() .iter() diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 8ee0c715a0ea5..b6a312c2982ac 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -14,6 +14,7 @@ #![feature(iter_intersperse)] #![feature(let_chains)] #![feature(never_type)] +#![feature(rustc_attrs)] #![recursion_limit = "256"] #![allow(rustdoc::private_intra_doc_links)] #![allow(rustc::potential_query_instability)] @@ -61,7 +62,7 @@ use rustc_span::{Span, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; use std::cell::{Cell, RefCell}; use std::collections::BTreeSet; -use std::{fmt, ptr}; +use std::fmt; use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion}; use imports::{Import, ImportData, ImportKind, NameResolution}; @@ -365,7 +366,7 @@ impl<'a> LexicalScopeBinding<'a> { } } -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] enum ModuleOrUniformRoot<'a> { /// Regular module. Module(Module<'a>), @@ -383,23 +384,6 @@ enum ModuleOrUniformRoot<'a> { CurrentScope, } -impl ModuleOrUniformRoot<'_> { - fn same_def(lhs: Self, rhs: Self) -> bool { - match (lhs, rhs) { - (ModuleOrUniformRoot::Module(lhs), ModuleOrUniformRoot::Module(rhs)) => { - ptr::eq(lhs, rhs) - } - ( - ModuleOrUniformRoot::CrateRootAndExternPrelude, - ModuleOrUniformRoot::CrateRootAndExternPrelude, - ) - | (ModuleOrUniformRoot::ExternPrelude, ModuleOrUniformRoot::ExternPrelude) - | (ModuleOrUniformRoot::CurrentScope, ModuleOrUniformRoot::CurrentScope) => true, - _ => false, - } - } -} - #[derive(Debug)] enum PathResult<'a> { Module(ModuleOrUniformRoot<'a>), @@ -530,7 +514,9 @@ struct ModuleData<'a> { expansion: ExpnId, } -type Module<'a> = &'a ModuleData<'a>; +#[derive(Clone, Copy, PartialEq)] +#[rustc_pass_by_value] +struct Module<'a>(Interned<'a, ModuleData<'a>>); impl<'a> ModuleData<'a> { fn new( @@ -558,8 +544,10 @@ impl<'a> ModuleData<'a> { expansion, } } +} - fn for_each_child<'tcx, R, F>(&'a self, resolver: &mut R, mut f: F) +impl<'a> Module<'a> { + fn for_each_child<'tcx, R, F>(self, resolver: &mut R, mut f: F) where R: AsMut>, F: FnMut(&mut R, Ident, Namespace, NameBinding<'a>), @@ -572,7 +560,7 @@ impl<'a> ModuleData<'a> { } /// This modifies `self` in place. The traits will be stored in `self.traits`. - fn ensure_traits<'tcx, R>(&'a self, resolver: &mut R) + fn ensure_traits<'tcx, R>(self, resolver: &mut R) where R: AsMut>, { @@ -591,7 +579,7 @@ impl<'a> ModuleData<'a> { } } - fn res(&self) -> Option { + fn res(self) -> Option { match self.kind { ModuleKind::Def(kind, def_id, _) => Some(Res::Def(kind, def_id)), _ => None, @@ -599,11 +587,11 @@ impl<'a> ModuleData<'a> { } // Public for rustdoc. - fn def_id(&self) -> DefId { + fn def_id(self) -> DefId { self.opt_def_id().expect("`ModuleData::def_id` is called on a block module") } - fn opt_def_id(&self) -> Option { + fn opt_def_id(self) -> Option { match self.kind { ModuleKind::Def(_, def_id, _) => Some(def_id), _ => None, @@ -611,15 +599,15 @@ impl<'a> ModuleData<'a> { } // `self` resolves to the first module ancestor that `is_normal`. - fn is_normal(&self) -> bool { + fn is_normal(self) -> bool { matches!(self.kind, ModuleKind::Def(DefKind::Mod, _, _)) } - fn is_trait(&self) -> bool { + fn is_trait(self) -> bool { matches!(self.kind, ModuleKind::Def(DefKind::Trait, _, _)) } - fn nearest_item_scope(&'a self) -> Module<'a> { + fn nearest_item_scope(self) -> Module<'a> { match self.kind { ModuleKind::Def(DefKind::Enum | DefKind::Trait, ..) => { self.parent.expect("enum or trait module without a parent") @@ -630,15 +618,15 @@ impl<'a> ModuleData<'a> { /// The [`DefId`] of the nearest `mod` item ancestor (which may be this module). /// This may be the crate root. - fn nearest_parent_mod(&self) -> DefId { + fn nearest_parent_mod(self) -> DefId { match self.kind { ModuleKind::Def(DefKind::Mod, def_id, _) => def_id, _ => self.parent.expect("non-root module without parent").nearest_parent_mod(), } } - fn is_ancestor_of(&self, mut other: &Self) -> bool { - while !ptr::eq(self, other) { + fn is_ancestor_of(self, mut other: Self) -> bool { + while self != other { if let Some(parent) = other.parent { other = parent; } else { @@ -649,7 +637,15 @@ impl<'a> ModuleData<'a> { } } -impl<'a> fmt::Debug for ModuleData<'a> { +impl<'a> std::ops::Deref for Module<'a> { + type Target = ModuleData<'a>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl<'a> fmt::Debug for Module<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self.res()) } @@ -810,10 +806,9 @@ impl<'a> NameBindingData<'a> { NameBindingKind::Import { import, .. } => { matches!(import.kind, ImportKind::ExternCrate { .. }) } - NameBindingKind::Module(&ModuleData { - kind: ModuleKind::Def(DefKind::Mod, def_id, _), - .. - }) => def_id.is_crate_root(), + NameBindingKind::Module(module) + if let ModuleKind::Def(DefKind::Mod, def_id, _) = module.kind + => def_id.is_crate_root(), _ => false, } } @@ -1102,8 +1097,13 @@ impl<'a> ResolverArenas<'a> { no_implicit_prelude: bool, module_map: &mut FxHashMap>, ) -> Module<'a> { - let module = - self.modules.alloc(ModuleData::new(parent, kind, expn_id, span, no_implicit_prelude)); + let module = Module(Interned::new_unchecked(self.modules.alloc(ModuleData::new( + parent, + kind, + expn_id, + span, + no_implicit_prelude, + )))); let def_id = module.opt_def_id(); if def_id.map_or(true, |def_id| def_id.is_local()) { self.local_modules.borrow_mut().push(module); @@ -1647,7 +1647,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { module.populate_on_access.set(false); self.build_reduced_graph_external(module); } - &module.lazy_resolutions + &module.0.0.lazy_resolutions } fn resolution( @@ -1827,7 +1827,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn set_binding_parent_module(&mut self, binding: NameBinding<'a>, module: Module<'a>) { if let Some(old_module) = self.binding_parent_modules.insert(binding, module) { - if !ptr::eq(module, old_module) { + if module != old_module { span_bug!(binding.span, "parent module is reset for binding"); } } @@ -1847,7 +1847,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ) { (Some(macro_rules), Some(modularized)) => { macro_rules.nearest_parent_mod() == modularized.nearest_parent_mod() - && modularized.is_ancestor_of(macro_rules) + && modularized.is_ancestor_of(*macro_rules) } _ => false, } From 9f3fba8da81300dc1a734a9cb1e2d804286b4f8d Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 5 Jul 2023 13:46:42 +0300 Subject: [PATCH 07/18] resolve: Add comments explaining use of `Interned` --- compiler/rustc_resolve/src/imports.rs | 2 ++ compiler/rustc_resolve/src/lib.rs | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 036fbf2dbf0af..d37fe783bbac2 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -172,6 +172,8 @@ pub(crate) struct ImportData<'a> { pub used: Cell, } +/// All imports are unique and allocated on a same arena, +/// so we can use referential equality to compare them. pub(crate) type Import<'a> = Interned<'a, ImportData<'a>>; impl<'a> ImportData<'a> { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index b6a312c2982ac..da3d86a4718d7 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -514,6 +514,8 @@ struct ModuleData<'a> { expansion: ExpnId, } +/// All modules are unique and allocated on a same arena, +/// so we can use referential equality to compare them. #[derive(Clone, Copy, PartialEq)] #[rustc_pass_by_value] struct Module<'a>(Interned<'a, ModuleData<'a>>); @@ -661,6 +663,8 @@ struct NameBindingData<'a> { vis: ty::Visibility, } +/// All name bindings are unique and allocated on a same arena, +/// so we can use referential equality to compare them. type NameBinding<'a> = Interned<'a, NameBindingData<'a>>; trait ToNameBinding<'a> { From c6643b50ea7290daf0a9f0e33d1f27c6f52796ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 4 Jul 2023 19:40:48 +0200 Subject: [PATCH 08/18] Revert the lexing of c_str_literals --- compiler/rustc_lexer/src/lib.rs | 7 ---- .../rfcs/rfc-3348-c-string-literals/basic.rs | 4 +- .../rfc-3348-c-string-literals/basic.stderr | 25 ++++++++++++ .../rfcs/rfc-3348-c-string-literals/gate.rs | 6 ++- .../rfc-3348-c-string-literals/gate.stderr | 35 ++++++++++------ .../rfc-3348-c-string-literals/no-nuls.rs | Bin 565 -> 760 bytes .../rfc-3348-c-string-literals/no-nuls.stderr | Bin 674 -> 4477 bytes .../rfc-3348-c-string-literals/non-ascii.rs | 4 +- .../non-ascii.stderr | 38 ++++++++++++++++++ 9 files changed, 96 insertions(+), 23 deletions(-) create mode 100644 tests/ui/rfcs/rfc-3348-c-string-literals/basic.stderr create mode 100644 tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.stderr diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index d511d2b1280d9..29335a8c0f4cd 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -367,13 +367,6 @@ impl Cursor<'_> { Some(|terminated| Byte { terminated }), ), - // c-string literal, raw c-string literal or identifier. - 'c' => self.c_or_byte_string( - |terminated| CStr { terminated }, - |n_hashes| RawCStr { n_hashes }, - None, - ), - // Identifier (this should be checked after other variant that can // start as identifier). c if is_id_start(c) => self.ident_or_unknown_prefix(), diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs index e4b07ab8108e0..3fc5fd481ea6d 100644 --- a/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/basic.rs @@ -1,4 +1,6 @@ -// run-pass +// FIXME(c_str_literals): This should be `run-pass` +// known-bug: #113333 +// edition: 2021 #![feature(c_str_literals)] diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/basic.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/basic.stderr new file mode 100644 index 0000000000000..571c319d8c533 --- /dev/null +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/basic.stderr @@ -0,0 +1,25 @@ +error: prefix `c` is unknown + --> $DIR/basic.rs:8:27 + | +LL | assert_eq!(b"test\0", c"test".to_bytes_with_nul()); + | ^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | assert_eq!(b"test\0", c "test".to_bytes_with_nul()); + | + + +error: no rules expected the token `"test"` + --> $DIR/basic.rs:8:28 + | +LL | assert_eq!(b"test\0", c"test".to_bytes_with_nul()); + | -^^^^^ + | | + | no rules expected this token in macro call + | help: missing comma here + | + = note: while trying to match sequence start + +error: aborting due to 2 previous errors + diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/gate.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/gate.rs index b27da26ed23bb..ddd6d9a25daad 100644 --- a/tests/ui/rfcs/rfc-3348-c-string-literals/gate.rs +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/gate.rs @@ -1,4 +1,6 @@ // gate-test-c_str_literals +// known-bug: #113333 +// edition: 2021 macro_rules! m { ($t:tt) => {} @@ -6,8 +8,8 @@ macro_rules! m { fn main() { c"foo"; - //~^ ERROR: `c".."` literals are experimental + // FIXME(c_str_literals): This should be ``c".."` literals are experimental` m!(c"test"); - //~^ ERROR: `c".."` literals are experimental + // FIXME(c_str_literals): This should be ``c".."` literals are experimental` } diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr index bc0c537aada83..8de36ca4a6edf 100644 --- a/tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/gate.stderr @@ -1,21 +1,32 @@ -error[E0658]: `c".."` literals are experimental - --> $DIR/gate.rs:8:5 +error: prefix `c` is unknown + --> $DIR/gate.rs:10:5 | LL | c"foo"; - | ^^^^^^ + | ^ unknown prefix | - = note: see issue #105723 for more information - = help: add `#![feature(c_str_literals)]` to the crate attributes to enable + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | c "foo"; + | + -error[E0658]: `c".."` literals are experimental - --> $DIR/gate.rs:11:8 +error: prefix `c` is unknown + --> $DIR/gate.rs:13:8 | LL | m!(c"test"); - | ^^^^^^^ + | ^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here | - = note: see issue #105723 for more information - = help: add `#![feature(c_str_literals)]` to the crate attributes to enable +LL | m!(c "test"); + | + + +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `"foo"` + --> $DIR/gate.rs:10:6 + | +LL | c"foo"; + | ^^^^^ expected one of 8 possible tokens -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs index 7bc6097f124aabfded4a9e9791611cfe4fbf9f78..96945f125da71a9097f6f26c75a328f097448568 100644 GIT binary patch literal 760 zcmcJNO-sZu5Qg`hUoma>kP6avy>(F#*#$vQdJuM{o6V+eFij;NsFeP9W4gLhJlZ*h zcamo&GjEc>i)`QI`QBDJL|Jy>0woEs12?>tIV{pehENo2N=A%T4AVjzRS0gFB0|T{ z2$d2V!X=KOL*Rmj+caGIqa&?vpYB)VS2;Y^T!XG#D-N({u#;8@pfyp1IM$&HE6Vz|75 zu3sW|Kibf;!t3k1hm|vd^MGO6{N({>hu?dnKfSxeX+CuLli#$j9$@dIcremQ8dzg_ P7LFCq9*JKyoYbRF@$lQ` delta 167 zcmeytx|L<3h80&`oPujmkbjVs!enbkX+SIX)z%kSR(@bGAg5XJ85yzvbed2f%Rn4Ih5|y!^t&kXMB|mMR^m zC*}$sgNqA1njIh?T!n-4`ec1PSwG?VxvSyk(pPYyY5h8yfz60(HfJOirhJBiX_C{z z97uvBMe@#!QjF(>%Svg)VH^buD#{eO;L6-D!MGWx8Nb2(!rZUQsTsW>Nv=#dI`KIO z=-&ZEp^rfI5Qa}Zp|GK~Es4ZK;-DW88Zz6?f8?3})iUf$HaJRs6yzR`5S?vekb?%` zNmo5VqA3(U2zxMyJq#SX=_-O(vc=@TEk6GtlV~#^nqOIWKZQotw#oT$jeCafw@y%Qo3Q zPSCPEM;jBMN(!DFx@K1cWyzSFfW04Mhd1Y+KEI4HjfNE;5i#rWCql1B(8Y@nzCYRR fyP*I|{vI!G(MUg&)j`5rY|)T>DjOU+cR0qrx?#zt diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs index 82e8e2090d7db..066505c23dfc0 100644 --- a/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.rs @@ -1,4 +1,6 @@ -// run-pass +// FIXME(c_str_literals): This should be `run-pass` +// known-bug: #113333 +// edition: 2021 #![feature(c_str_literals)] diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.stderr b/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.stderr new file mode 100644 index 0000000000000..47361fb61d271 --- /dev/null +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/non-ascii.stderr @@ -0,0 +1,38 @@ +error: prefix `c` is unknown + --> $DIR/non-ascii.rs:9:9 + | +LL | c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(), + | ^ unknown prefix + | + = note: prefixed identifiers and literals are reserved since Rust 2021 +help: consider inserting whitespace here + | +LL | c "\xEF\x80🦀\u{1F980}".to_bytes_with_nul(), + | + + +error: out of range hex escape + --> $DIR/non-ascii.rs:9:11 + | +LL | c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(), + | ^^^^ must be a character in the range [\x00-\x7f] + +error: out of range hex escape + --> $DIR/non-ascii.rs:9:15 + | +LL | c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(), + | ^^^^ must be a character in the range [\x00-\x7f] + +error: no rules expected the token `"\xEF\x80🦀\u{1F980}"` + --> $DIR/non-ascii.rs:9:10 + | +LL | c"\xEF\x80🦀\u{1F980}".to_bytes_with_nul(), + | -^^^^^^^^^^^^^^^^^^^^ + | | + | no rules expected this token in macro call + | help: missing comma here + | +note: while trying to match `,` + --> $SRC_DIR/core/src/macros/mod.rs:LL:COL + +error: aborting due to 4 previous errors + From 5b25f9d8bdb4a5ffdaed4fb6ebdc521c6eba1b0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 4 Jul 2023 19:45:55 +0200 Subject: [PATCH 09/18] Revert "fix ptr cast" This reverts commit 2f459f7f140307b5abbb7ea81440ed1843b490e7. --- library/std/src/sys/unix/args.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs index f8fa81e6ef183..7b6f8810cbabd 100644 --- a/library/std/src/sys/unix/args.rs +++ b/library/std/src/sys/unix/args.rs @@ -242,15 +242,13 @@ mod imp { let mut res = Vec::new(); unsafe { - let process_info_sel = - sel_registerName(c"processInfo".as_ptr() as *const libc::c_uchar); - let arguments_sel = sel_registerName(c"arguments".as_ptr() as *const libc::c_uchar); - let utf8_sel = sel_registerName(c"UTF8String".as_ptr() as *const libc::c_uchar); - let count_sel = sel_registerName(c"count".as_ptr() as *const libc::c_uchar); - let object_at_sel = - sel_registerName(c"objectAtIndex:".as_ptr() as *const libc::c_uchar); - - let klass = objc_getClass(c"NSProcessInfo".as_ptr() as *const libc::c_uchar); + let process_info_sel = sel_registerName(c"processInfo".as_ptr()); + let arguments_sel = sel_registerName(c"arguments".as_ptr()); + let utf8_sel = sel_registerName(c"UTF8String".as_ptr()); + let count_sel = sel_registerName(c"count".as_ptr()); + let object_at_sel = sel_registerName(c"objectAtIndex:".as_ptr()); + + let klass = objc_getClass(c"NSProcessInfo".as_ptr()); let info = objc_msgSend(klass, process_info_sel); let args = objc_msgSend(info, arguments_sel); From 9dbe67fc8c722bc8df4a6a792677a93a073773f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 4 Jul 2023 19:45:58 +0200 Subject: [PATCH 10/18] Revert "use c literals in library" This reverts commit f212ba6d6d60963c8101bb24fc3e53fca80c046f. --- library/std/src/lib.rs | 1 - library/std/src/sys/unix/args.rs | 12 ++++++------ library/std/src/sys/unix/fs.rs | 2 +- library/std/src/sys/unix/mod.rs | 7 ++++--- library/std/src/sys/unix/process/process_common.rs | 9 +++++---- library/std/src/sys/unix/thread.rs | 3 ++- library/std/src/sys/windows/c.rs | 4 ++-- library/std/src/sys/windows/compat.rs | 6 +++--- library/std/src/sys/windows/mod.rs | 4 ++-- src/tools/tidy/src/deps.rs | 1 + 10 files changed, 26 insertions(+), 23 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index da08c018d0e36..72b9ad3480b32 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -241,7 +241,6 @@ #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] -#![feature(c_str_literals)] #![feature(c_unwind)] #![feature(cfg_target_thread_local)] #![feature(concat_idents)] diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs index 7b6f8810cbabd..eafd6821f540a 100644 --- a/library/std/src/sys/unix/args.rs +++ b/library/std/src/sys/unix/args.rs @@ -242,13 +242,13 @@ mod imp { let mut res = Vec::new(); unsafe { - let process_info_sel = sel_registerName(c"processInfo".as_ptr()); - let arguments_sel = sel_registerName(c"arguments".as_ptr()); - let utf8_sel = sel_registerName(c"UTF8String".as_ptr()); - let count_sel = sel_registerName(c"count".as_ptr()); - let object_at_sel = sel_registerName(c"objectAtIndex:".as_ptr()); + let process_info_sel = sel_registerName("processInfo\0".as_ptr()); + let arguments_sel = sel_registerName("arguments\0".as_ptr()); + let utf8_sel = sel_registerName("UTF8String\0".as_ptr()); + let count_sel = sel_registerName("count\0".as_ptr()); + let object_at_sel = sel_registerName("objectAtIndex:\0".as_ptr()); - let klass = objc_getClass(c"NSProcessInfo".as_ptr()); + let klass = objc_getClass("NSProcessInfo\0".as_ptr()); let info = objc_msgSend(klass, process_info_sel); let args = objc_msgSend(info, arguments_sel); diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 9cf5cfcc8d552..fbc7f04ce9ae0 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1097,7 +1097,7 @@ impl File { cfg_has_statx! { if let Some(ret) = unsafe { try_statx( fd, - c"".as_ptr() as *const c_char, + b"\0" as *const _ as *const c_char, libc::AT_EMPTY_PATH | libc::AT_STATX_SYNC_AS_STAT, libc::STATX_ALL, ) } { diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index 1b72e21a83285..326f1481e1918 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -1,5 +1,6 @@ #![allow(missing_docs, nonstandard_style)] +use crate::ffi::CStr; use crate::io::ErrorKind; pub use self::rand::hashmap_random_keys; @@ -74,7 +75,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { // thread-id for the main thread and so renaming the main thread will rename the // process and we only want to enable this on platforms we've tested. if cfg!(target_os = "macos") { - thread::Thread::set_name(&c"main"); + thread::Thread::set_name(&CStr::from_bytes_with_nul_unchecked(b"main\0")); } unsafe fn sanitize_standard_fds() { @@ -121,7 +122,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { if pfd.revents & libc::POLLNVAL == 0 { continue; } - if open64(c"/dev/null".as_ptr().cast(), libc::O_RDWR, 0) == -1 { + if open64("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 { // If the stream is closed but we failed to reopen it, abort the // process. Otherwise we wouldn't preserve the safety of // operations on the corresponding Rust object Stdin, Stdout, or @@ -151,7 +152,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) { use libc::open64; for fd in 0..3 { if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF { - if open64(c"/dev/null".as_ptr().cast(), libc::O_RDWR, 0) == -1 { + if open64("/dev/null\0".as_ptr().cast(), libc::O_RDWR, 0) == -1 { // If the stream is closed but we failed to reopen it, abort the // process. Otherwise we wouldn't preserve the safety of // operations on the corresponding Rust object Stdin, Stdout, or diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs index 5f316b12b625d..640648e870748 100644 --- a/library/std/src/sys/unix/process/process_common.rs +++ b/library/std/src/sys/unix/process/process_common.rs @@ -24,11 +24,11 @@ cfg_if::cfg_if! { if #[cfg(target_os = "fuchsia")] { // fuchsia doesn't have /dev/null } else if #[cfg(target_os = "redox")] { - const DEV_NULL: &CStr = c"null:"; + const DEV_NULL: &str = "null:\0"; } else if #[cfg(target_os = "vxworks")] { - const DEV_NULL: &CStr = c"/null"; + const DEV_NULL: &str = "/null\0"; } else { - const DEV_NULL: &CStr = c"/dev/null"; + const DEV_NULL: &str = "/dev/null\0"; } } @@ -474,7 +474,8 @@ impl Stdio { let mut opts = OpenOptions::new(); opts.read(readable); opts.write(!readable); - let fd = File::open_c(DEV_NULL, &opts)?; + let path = unsafe { CStr::from_ptr(DEV_NULL.as_ptr() as *const _) }; + let fd = File::open_c(&path, &opts)?; Ok((ChildStdio::Owned(fd.into_inner()), None)) } diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index 893f8b8df3f54..4f2d9cf36553f 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -163,9 +163,10 @@ impl Thread { #[cfg(target_os = "netbsd")] pub fn set_name(name: &CStr) { unsafe { + let cname = CStr::from_bytes_with_nul_unchecked(b"%s\0".as_slice()); let res = libc::pthread_setname_np( libc::pthread_self(), - c"%s".as_ptr(), + cname.as_ptr(), name.as_ptr() as *mut libc::c_void, ); debug_assert_eq!(res, 0); diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index b1b9e84fce9e9..d9ccba0e9da76 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -321,7 +321,7 @@ pub unsafe fn NtWriteFile( // Functions that aren't available on every version of Windows that we support, // but we still use them and just provide some form of a fallback implementation. compat_fn_with_fallback! { - pub static KERNEL32: &CStr = c"kernel32"; + pub static KERNEL32: &CStr = ansi_str!("kernel32"); // >= Win10 1607 // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription @@ -354,7 +354,7 @@ compat_fn_optional! { } compat_fn_with_fallback! { - pub static NTDLL: &CStr = c"ntdll"; + pub static NTDLL: &CStr = ansi_str!("ntdll"); pub fn NtCreateKeyedEvent( KeyedEventHandle: LPHANDLE, diff --git a/library/std/src/sys/windows/compat.rs b/library/std/src/sys/windows/compat.rs index 649cc4bfdbf1a..4fe95d41116b5 100644 --- a/library/std/src/sys/windows/compat.rs +++ b/library/std/src/sys/windows/compat.rs @@ -228,9 +228,9 @@ macro_rules! compat_fn_optional { /// Load all needed functions from "api-ms-win-core-synch-l1-2-0". pub(super) fn load_synch_functions() { fn try_load() -> Option<()> { - const MODULE_NAME: &CStr = c"api-ms-win-core-synch-l1-2-0"; - const WAIT_ON_ADDRESS: &CStr = c"WaitOnAddress"; - const WAKE_BY_ADDRESS_SINGLE: &CStr = c"WakeByAddressSingle"; + const MODULE_NAME: &CStr = ansi_str!("api-ms-win-core-synch-l1-2-0"); + const WAIT_ON_ADDRESS: &CStr = ansi_str!("WaitOnAddress"); + const WAKE_BY_ADDRESS_SINGLE: &CStr = ansi_str!("WakeByAddressSingle"); // Try loading the library and all the required functions. // If any step fails, then they all fail. diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs index b11c89622032e..bcc172b0fae36 100644 --- a/library/std/src/sys/windows/mod.rs +++ b/library/std/src/sys/windows/mod.rs @@ -1,6 +1,6 @@ #![allow(missing_docs, nonstandard_style)] -use crate::ffi::{OsStr, OsString}; +use crate::ffi::{CStr, OsStr, OsString}; use crate::io::ErrorKind; use crate::mem::MaybeUninit; use crate::os::windows::ffi::{OsStrExt, OsStringExt}; @@ -51,7 +51,7 @@ pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) { // Normally, `thread::spawn` will call `Thread::set_name` but since this thread already // exists, we have to call it ourselves. - thread::Thread::set_name(&c"main"); + thread::Thread::set_name(&CStr::from_bytes_with_nul_unchecked(b"main\0")); } // SAFETY: must be called only once during runtime cleanup. diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 1f6c0b75a09df..ecc84c1618c0f 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -131,6 +131,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "crossbeam-epoch", "crossbeam-utils", "crypto-common", + "cstr", "datafrog", "derive_more", "digest", From 3788b7ab32a6398e7563557f7b32f741f43704a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 4 Jul 2023 19:53:44 +0200 Subject: [PATCH 11/18] Revert "use new c literals instead of cstr! macro" This reverts commit a17561ffc90c900cb7d0e96b00c6381244764ef7. --- Cargo.lock | 11 +++++ compiler/rustc_codegen_llvm/Cargo.toml | 1 + compiler/rustc_codegen_llvm/src/allocator.rs | 4 +- compiler/rustc_codegen_llvm/src/back/lto.rs | 2 +- compiler/rustc_codegen_llvm/src/back/write.rs | 16 +++---- compiler/rustc_codegen_llvm/src/base.rs | 6 ++- compiler/rustc_codegen_llvm/src/builder.rs | 16 +++++-- compiler/rustc_codegen_llvm/src/consts.rs | 7 +-- compiler/rustc_codegen_llvm/src/context.rs | 44 +++++++++---------- .../rustc_codegen_llvm/src/debuginfo/gdb.rs | 3 +- .../src/debuginfo/metadata.rs | 9 ++-- .../rustc_codegen_llvm/src/debuginfo/mod.rs | 7 +-- compiler/rustc_codegen_llvm/src/lib.rs | 1 - 13 files changed, 75 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cdf6a4cc2de2f..54d74ab6a7517 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -766,6 +766,16 @@ dependencies = [ "typenum", ] +[[package]] +name = "cstr" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c11a39d776a3b35896711da8a04dc1835169dcd36f710878187637314e47941b" +dependencies = [ + "proc-macro2", + "quote", +] + [[package]] name = "ctrlc" version = "3.4.0" @@ -3016,6 +3026,7 @@ name = "rustc_codegen_llvm" version = "0.0.0" dependencies = [ "bitflags 1.3.2", + "cstr", "libc", "measureme", "object", diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index 39ff3a0ba2d22..ad51f2d095857 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -8,6 +8,7 @@ test = false [dependencies] bitflags = "1.0" +cstr = "0.2" libc = "0.2" measureme = "10.0.0" object = { version = "0.31.1", default-features = false, features = [ diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index ad0636894b793..a57508815d6f8 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -77,7 +77,7 @@ pub(crate) unsafe fn codegen( llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty); llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden); - let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, c"entry".as_ptr().cast()); + let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast()); let llbuilder = llvm::LLVMCreateBuilderInContext(llcx); llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb); @@ -129,7 +129,7 @@ pub(crate) unsafe fn codegen( attributes::apply_to_llfn(callee, llvm::AttributePlace::Function, &[no_return]); llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden); - let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, c"entry".as_ptr().cast()); + let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast()); let llbuilder = llvm::LLVMCreateBuilderInContext(llcx); llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb); diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 94885b40cc1a1..d7dd98d79389c 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -601,7 +601,7 @@ pub(crate) fn run_pass_manager( llvm::LLVMRustAddModuleFlag( module.module_llvm.llmod(), llvm::LLVMModFlagBehavior::Error, - c"LTOPostLink".as_ptr().cast(), + "LTOPostLink\0".as_ptr().cast(), 1, ); } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 998e3b300da9e..0f5e975445fae 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -931,16 +931,16 @@ unsafe fn embed_bitcode( let llglobal = llvm::LLVMAddGlobal( llmod, common::val_ty(llconst), - c"rustc.embedded.module".as_ptr().cast(), + "rustc.embedded.module\0".as_ptr().cast(), ); llvm::LLVMSetInitializer(llglobal, llconst); let section = if is_apple { - c"__LLVM,__bitcode" + "__LLVM,__bitcode\0" } else if is_aix { - c".ipa" + ".ipa\0" } else { - c".llvmbc" + ".llvmbc\0" }; llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); @@ -950,15 +950,15 @@ unsafe fn embed_bitcode( let llglobal = llvm::LLVMAddGlobal( llmod, common::val_ty(llconst), - c"rustc.embedded.cmdline".as_ptr().cast(), + "rustc.embedded.cmdline\0".as_ptr().cast(), ); llvm::LLVMSetInitializer(llglobal, llconst); let section = if is_apple { - c"__LLVM,__cmdline" + "__LLVM,__cmdline\0" } else if is_aix { - c".info" + ".info\0" } else { - c".llvmcmd" + ".llvmcmd\0" }; llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index 2f7eb08ad3d4c..5b2bbdb4bde1e 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -19,6 +19,8 @@ use crate::context::CodegenCx; use crate::llvm; use crate::value::Value; +use cstr::cstr; + use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::*; @@ -108,11 +110,11 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen // Create the llvm.used and llvm.compiler.used variables. if !cx.used_statics.borrow().is_empty() { - cx.create_used_variable_impl(c"llvm.used", &*cx.used_statics.borrow()); + cx.create_used_variable_impl(cstr!("llvm.used"), &*cx.used_statics.borrow()); } if !cx.compiler_used_statics.borrow().is_empty() { cx.create_used_variable_impl( - c"llvm.compiler.used", + cstr!("llvm.compiler.used"), &*cx.compiler_used_statics.borrow(), ); } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 9863ca3520239..d55992bf092f8 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -6,6 +6,7 @@ use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, True} use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; +use cstr::cstr; use libc::{c_char, c_uint}; use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, SynchronizationScope, TypeKind}; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; @@ -25,6 +26,7 @@ use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange}; use rustc_target::spec::{HasTargetSpec, SanitizerSet, Target}; use smallvec::SmallVec; use std::borrow::Cow; +use std::ffi::CStr; use std::iter; use std::ops::Deref; use std::ptr; @@ -44,10 +46,13 @@ impl Drop for Builder<'_, '_, '_> { } } +// FIXME(eddyb) use a checked constructor when they become `const fn`. +const EMPTY_C_STR: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(b"\0") }; + /// Empty string, to be used where LLVM expects an instruction name, indicating /// that the instruction is to be left unnamed (i.e. numbered, in textual IR). // FIXME(eddyb) pass `&CStr` directly to FFI once it's a thin pointer. -const UNNAMED: *const c_char = c"".as_ptr(); +const UNNAMED: *const c_char = EMPTY_C_STR.as_ptr(); impl<'ll, 'tcx> BackendTypes for Builder<'_, 'll, 'tcx> { type Value = as BackendTypes>::Value; @@ -1002,13 +1007,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn cleanup_pad(&mut self, parent: Option<&'ll Value>, args: &[&'ll Value]) -> Funclet<'ll> { + let name = cstr!("cleanuppad"); let ret = unsafe { llvm::LLVMBuildCleanupPad( self.llbuilder, parent, args.as_ptr(), args.len() as c_uint, - c"cleanuppad".as_ptr(), + name.as_ptr(), ) }; Funclet::new(ret.expect("LLVM does not have support for cleanuppad")) @@ -1022,13 +1028,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } fn catch_pad(&mut self, parent: &'ll Value, args: &[&'ll Value]) -> Funclet<'ll> { + let name = cstr!("catchpad"); let ret = unsafe { llvm::LLVMBuildCatchPad( self.llbuilder, parent, args.as_ptr(), args.len() as c_uint, - c"catchpad".as_ptr(), + name.as_ptr(), ) }; Funclet::new(ret.expect("LLVM does not have support for catchpad")) @@ -1040,13 +1047,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { unwind: Option<&'ll BasicBlock>, handlers: &[&'ll BasicBlock], ) -> &'ll Value { + let name = cstr!("catchswitch"); let ret = unsafe { llvm::LLVMBuildCatchSwitch( self.llbuilder, parent, unwind, handlers.len() as c_uint, - c"catchswitch".as_ptr(), + name.as_ptr(), ) }; let ret = ret.expect("LLVM does not have support for catchswitch"); diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index 2087754c66b84..df52f50f86f05 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -8,6 +8,7 @@ use crate::llvm::{self, True}; use crate::type_::Type; use crate::type_of::LayoutLlvmExt; use crate::value::Value; +use cstr::cstr; use rustc_codegen_ssa::traits::*; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; @@ -481,9 +482,9 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { .all(|&byte| byte == 0); let sect_name = if all_bytes_are_zero { - c"__DATA,__thread_bss" + cstr!("__DATA,__thread_bss") } else { - c"__DATA,__thread_data" + cstr!("__DATA,__thread_data") }; llvm::LLVMSetSection(g, sect_name.as_ptr()); } @@ -512,7 +513,7 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { let val = llvm::LLVMMetadataAsValue(self.llcx, meta); llvm::LLVMAddNamedMetadataOperand( self.llmod, - c"wasm.custom_sections".as_ptr().cast(), + "wasm.custom_sections\0".as_ptr().cast(), val, ); } diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 287a22bc9a6c5..e1e0a442845de 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -8,6 +8,7 @@ use crate::llvm_util; use crate::type_::Type; use crate::value::Value; +use cstr::cstr; use rustc_codegen_ssa::base::{wants_msvc_seh, wants_wasm_eh}; use rustc_codegen_ssa::traits::*; use rustc_data_structures::base_n; @@ -223,42 +224,36 @@ pub unsafe fn create_module<'ll>( // If skipping the PLT is enabled, we need to add some module metadata // to ensure intrinsic calls don't use it. if !sess.needs_plt() { - llvm::LLVMRustAddModuleFlag( - llmod, - llvm::LLVMModFlagBehavior::Warning, - c"RtLibUseGOT".as_ptr().cast(), - 1, - ); + let avoid_plt = "RtLibUseGOT\0".as_ptr().cast(); + llvm::LLVMRustAddModuleFlag(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1); } // Enable canonical jump tables if CFI is enabled. (See https://reviews.llvm.org/D65629.) if sess.is_sanitizer_cfi_canonical_jump_tables_enabled() && sess.is_sanitizer_cfi_enabled() { + let canonical_jump_tables = "CFI Canonical Jump Tables\0".as_ptr().cast(); llvm::LLVMRustAddModuleFlag( llmod, llvm::LLVMModFlagBehavior::Override, - c"CFI Canonical Jump Tables".as_ptr().cast(), + canonical_jump_tables, 1, ); } // Enable LTO unit splitting if specified or if CFI is enabled. (See https://reviews.llvm.org/D53891.) if sess.is_split_lto_unit_enabled() || sess.is_sanitizer_cfi_enabled() { + let enable_split_lto_unit = "EnableSplitLTOUnit\0".as_ptr().cast(); llvm::LLVMRustAddModuleFlag( llmod, llvm::LLVMModFlagBehavior::Override, - c"EnableSplitLTOUnit".as_ptr().cast(), + enable_split_lto_unit, 1, ); } // Add "kcfi" module flag if KCFI is enabled. (See https://reviews.llvm.org/D119296.) if sess.is_sanitizer_kcfi_enabled() { - llvm::LLVMRustAddModuleFlag( - llmod, - llvm::LLVMModFlagBehavior::Override, - c"kcfi".as_ptr().cast(), - 1, - ); + let kcfi = "kcfi\0".as_ptr().cast(); + llvm::LLVMRustAddModuleFlag(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1); } // Control Flow Guard is currently only supported by the MSVC linker on Windows. @@ -270,7 +265,7 @@ pub unsafe fn create_module<'ll>( llvm::LLVMRustAddModuleFlag( llmod, llvm::LLVMModFlagBehavior::Warning, - c"cfguard".as_ptr() as *const _, + "cfguard\0".as_ptr() as *const _, 1, ) } @@ -279,7 +274,7 @@ pub unsafe fn create_module<'ll>( llvm::LLVMRustAddModuleFlag( llmod, llvm::LLVMModFlagBehavior::Warning, - c"cfguard".as_ptr() as *const _, + "cfguard\0".as_ptr() as *const _, 2, ) } @@ -297,26 +292,26 @@ pub unsafe fn create_module<'ll>( llvm::LLVMRustAddModuleFlag( llmod, behavior, - c"branch-target-enforcement".as_ptr().cast(), + "branch-target-enforcement\0".as_ptr().cast(), bti.into(), ); llvm::LLVMRustAddModuleFlag( llmod, behavior, - c"sign-return-address".as_ptr().cast(), + "sign-return-address\0".as_ptr().cast(), pac_ret.is_some().into(), ); let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A }); llvm::LLVMRustAddModuleFlag( llmod, behavior, - c"sign-return-address-all".as_ptr().cast(), + "sign-return-address-all\0".as_ptr().cast(), pac_opts.leaf.into(), ); llvm::LLVMRustAddModuleFlag( llmod, behavior, - c"sign-return-address-with-bkey".as_ptr().cast(), + "sign-return-address-with-bkey\0".as_ptr().cast(), u32::from(pac_opts.key == PAuthKey::B), ); } else { @@ -332,7 +327,7 @@ pub unsafe fn create_module<'ll>( llvm::LLVMRustAddModuleFlag( llmod, llvm::LLVMModFlagBehavior::Override, - c"cf-protection-branch".as_ptr().cast(), + "cf-protection-branch\0".as_ptr().cast(), 1, ) } @@ -340,7 +335,7 @@ pub unsafe fn create_module<'ll>( llvm::LLVMRustAddModuleFlag( llmod, llvm::LLVMModFlagBehavior::Override, - c"cf-protection-return".as_ptr().cast(), + "cf-protection-return\0".as_ptr().cast(), 1, ) } @@ -349,7 +344,7 @@ pub unsafe fn create_module<'ll>( llvm::LLVMRustAddModuleFlag( llmod, llvm::LLVMModFlagBehavior::Error, - c"Virtual Function Elim".as_ptr().cast(), + "Virtual Function Elim\0".as_ptr().cast(), 1, ); } @@ -481,13 +476,14 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { } pub(crate) fn create_used_variable_impl(&self, name: &'static CStr, values: &[&'ll Value]) { + let section = cstr!("llvm.metadata"); let array = self.const_array(self.type_ptr_to(self.type_i8()), values); unsafe { let g = llvm::LLVMAddGlobal(self.llmod, self.val_ty(array), name.as_ptr()); llvm::LLVMSetInitializer(g, array); llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage); - llvm::LLVMSetSection(g, c"llvm.metadata".as_ptr()); + llvm::LLVMSetSection(g, section.as_ptr()); } } } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs index 8be54b7eb7188..37f30917609ae 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs @@ -38,6 +38,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global<'ll>(cx: &CodegenCx<'ll, ' unsafe { llvm::LLVMGetNamedGlobal(cx.llmod, c_section_var_name.as_ptr().cast()) }; section_var.unwrap_or_else(|| { + let section_name = b".debug_gdb_scripts\0"; let mut section_contents = Vec::new(); // Add the pretty printers for the standard library first. @@ -70,7 +71,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global<'ll>(cx: &CodegenCx<'ll, ' let section_var = cx .define_global(section_var_name, llvm_type) .unwrap_or_else(|| bug!("symbol `{}` is already defined", section_var_name)); - llvm::LLVMSetSection(section_var, c".debug_gdb_scripts".as_ptr().cast()); + llvm::LLVMSetSection(section_var, section_name.as_ptr().cast()); llvm::LLVMSetInitializer(section_var, cx.const_bytes(section_contents)); llvm::LLVMSetGlobalConstant(section_var, llvm::True); llvm::LLVMSetUnnamedAddress(section_var, llvm::UnnamedAddr::Global); diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 4b88ab8a97a85..ad07d637106b0 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -20,6 +20,7 @@ use crate::llvm::debuginfo::{ }; use crate::value::Value; +use cstr::cstr; use rustc_codegen_ssa::debuginfo::type_names::cpp_like_debuginfo; use rustc_codegen_ssa::debuginfo::type_names::VTableNameKind; use rustc_codegen_ssa::traits::*; @@ -811,6 +812,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( let name_in_debuginfo = name_in_debuginfo.to_string_lossy(); let work_dir = tcx.sess.opts.working_dir.to_string_lossy(FileNameDisplayPreference::Remapped); + let flags = "\0"; let output_filenames = tcx.output_filenames(()); let split_name = if tcx.sess.target_can_use_split_dwarf() { output_filenames @@ -847,7 +849,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( producer.as_ptr().cast(), producer.len(), tcx.sess.opts.optimize != config::OptLevel::No, - c"".as_ptr().cast(), + flags.as_ptr().cast(), 0, // NB: this doesn't actually have any perceptible effect, it seems. LLVM will instead // put the path supplied to `MCSplitDwarfFile` into the debug info of the final @@ -876,7 +878,8 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( ); let val = llvm::LLVMMetadataAsValue(debug_context.llcontext, gcov_metadata); - llvm::LLVMAddNamedMetadataOperand(debug_context.llmod, c"llvm.gcov".as_ptr(), val); + let llvm_gcov_ident = cstr!("llvm.gcov"); + llvm::LLVMAddNamedMetadataOperand(debug_context.llmod, llvm_gcov_ident.as_ptr(), val); } // Insert `llvm.ident` metadata on the wasm targets since that will @@ -889,7 +892,7 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>( ); llvm::LLVMAddNamedMetadataOperand( debug_context.llmod, - c"llvm.ident".as_ptr(), + cstr!("llvm.ident").as_ptr(), llvm::LLVMMDNodeInContext(debug_context.llcontext, &name_metadata, 1), ); } diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index c2f16cad3fcb1..0858f6b5f8eb6 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -113,7 +113,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { llvm::LLVMRustAddModuleFlag( self.llmod, llvm::LLVMModFlagBehavior::Warning, - c"Dwarf Version".as_ptr().cast(), + "Dwarf Version\0".as_ptr().cast(), dwarf_version, ); } else { @@ -121,16 +121,17 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> { llvm::LLVMRustAddModuleFlag( self.llmod, llvm::LLVMModFlagBehavior::Warning, - c"CodeView".as_ptr().cast(), + "CodeView\0".as_ptr().cast(), 1, ) } // Prevent bitcode readers from deleting the debug info. + let ptr = "Debug Info Version\0".as_ptr(); llvm::LLVMRustAddModuleFlag( self.llmod, llvm::LLVMModFlagBehavior::Warning, - c"Debug Info Version".as_ptr().cast(), + ptr.cast(), llvm::LLVMRustDebugMetadataVersion(), ); } diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 24968e00cc8e5..24ba28bbc82c2 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -11,7 +11,6 @@ #![feature(let_chains)] #![feature(never_type)] #![feature(impl_trait_in_assoc_type)] -#![feature(c_str_literals)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] From 22fd6a6abf1f97b488278cd142cc7fe721beb92a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 4 Jul 2023 20:37:17 +0200 Subject: [PATCH 12/18] Add regression test --- .../edition-2015-2018-lexing.rs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 tests/ui/rfcs/rfc-3348-c-string-literals/edition-2015-2018-lexing.rs diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/edition-2015-2018-lexing.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/edition-2015-2018-lexing.rs new file mode 100644 index 0000000000000..2a4cd60042609 --- /dev/null +++ b/tests/ui/rfcs/rfc-3348-c-string-literals/edition-2015-2018-lexing.rs @@ -0,0 +1,24 @@ +// Regression test for issue #113235. + +// check-pass +// revisions: edition2015 edition2018 +//[edition2015] edition: 2015 +//[edition2018] edition: 2018 + +// Make sure that in pre-2021 editions we continue to parse the snippet +// `c"hello"` as an identifier followed by a (normal) string literal and +// allow the code below to compile. +// Prefixes including `c` as used by C string literals are only reserved +// in edition 2021 and onward. +// +// Consider checking out rust-2021/reserved-prefixes-migration.rs as well. + +macro_rules! parse { + (c $e:expr) => { + $e + }; +} + +fn main() { + let _: &'static str = parse!(c"hello"); +} From 6c7017fa0a49f170bbe9d0053b72f996770fdb42 Mon Sep 17 00:00:00 2001 From: jyn Date: Wed, 5 Jul 2023 10:51:34 -0500 Subject: [PATCH 13/18] Fix submodule handling when the current branch is named after a tag If: 1. The current branch has the same name as git tag, and 2. The current branch is set to track a remote other than `origin`, and 3. We try to update a submodule then we'll get the following error: ``` ; x c Updating submodule src/doc/reference remote: Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 fatal: 'personal' does not appear to be a git repository fatal: Could not read from remote repository. ``` The problem is that 1. causes `git symbolic-ref --short HEAD` to try and disambiguate the branch from the tag using `heads/branch-name`, which breaks a previous workaround for a bug in `git submodule update` that uses the wrong remote. Adapt the workaround to strip `heads/` from the output. --- src/bootstrap/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 6a51450a777e8..0a7aff62257a5 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -599,6 +599,9 @@ impl Build { let mut git = self.config.git(); if let Some(branch) = current_branch { + // If there is a tag named after the current branch, git will try to disambiguate by prepending `heads/` to the branch name. + // This syntax isn't accepted by `branch.{branch}`. Strip it. + let branch = branch.strip_prefix("heads/").unwrap_or(&branch); git.arg("-c").arg(format!("branch.{branch}.remote=origin")); } git.args(&["submodule", "update", "--init", "--recursive", "--depth=1"]); From 40f2fbf61e8daf19a06a237e35e94aafdc649fc7 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 29 Jun 2023 23:50:42 +0900 Subject: [PATCH 14/18] Add a regression test for #112895 Signed-off-by: Yuki Okushi --- ...ds-not-checked-with-right-substitutions.rs | 29 +++++++++++++++++++ ...ot-checked-with-right-substitutions.stderr | 11 +++++++ 2 files changed, 40 insertions(+) create mode 100644 tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.rs create mode 100644 tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr diff --git a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.rs b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.rs new file mode 100644 index 0000000000000..05d205266b442 --- /dev/null +++ b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.rs @@ -0,0 +1,29 @@ +// This test checks that we correctly reject the following unsound code. + +trait Lengthen { + fn lengthen(self) -> T; +} + +impl<'a> Lengthen<&'a str> for &'a str { + fn lengthen(self) -> &'a str { self } +} + +trait Gat { + type Gat<'a>: for<'b> Lengthen>; + + fn lengthen(s: Self::Gat<'_>) -> Self::Gat<'static> { + s.lengthen() + } +} + +impl Gat for () { + type Gat<'a> = &'a str; //~ ERROR: implementation of `Lengthen` is not general enough +} + +fn main() { + let s = "hello, garbage".to_string(); + let borrow: &'static str = <() as Gat>::lengthen(&s); + drop(s); + + println!("{borrow}"); +} diff --git a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr new file mode 100644 index 0000000000000..7ea7a7b2de7bc --- /dev/null +++ b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr @@ -0,0 +1,11 @@ +error: implementation of `Lengthen` is not general enough + --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:20:20 + | +LL | type Gat<'a> = &'a str; + | ^^^^^^^ implementation of `Lengthen` is not general enough + | + = note: `Lengthen<&'0 str>` would have to be implemented for the type `&'a str`, for any lifetime `'0`... + = note: ...but `Lengthen<&'1 str>` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` + +error: aborting due to previous error + From 5a6c618d1ab59139b602a3b07572a9fb056c94ec Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 3 May 2023 02:56:36 +0000 Subject: [PATCH 15/18] Clarify that style guide does not cover nightly-only features --- src/doc/style-guide/src/SUMMARY.md | 1 + src/doc/style-guide/src/nightly.md | 3 +++ 2 files changed, 4 insertions(+) create mode 100644 src/doc/style-guide/src/nightly.md diff --git a/src/doc/style-guide/src/SUMMARY.md b/src/doc/style-guide/src/SUMMARY.md index 59fe9fdc6694a..606485bfb6c7e 100644 --- a/src/doc/style-guide/src/SUMMARY.md +++ b/src/doc/style-guide/src/SUMMARY.md @@ -9,3 +9,4 @@ - [Other style advice](advice.md) - [`Cargo.toml` conventions](cargo.md) - [Guiding principles and rationale](principles.md) +- [Nightly-only syntax](nightly.md) diff --git a/src/doc/style-guide/src/nightly.md b/src/doc/style-guide/src/nightly.md new file mode 100644 index 0000000000000..5a2815c71f13d --- /dev/null +++ b/src/doc/style-guide/src/nightly.md @@ -0,0 +1,3 @@ +The style guide does not prescribe formatting for nightly-only syntax. Refer to +the style team policy for nightly formatting procedure regarding breaking +formatter changes and feature stabilization. From 5957f028a1019f306b131299e6e653d942f809e9 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 21 Jun 2023 17:08:42 -0700 Subject: [PATCH 16/18] style-guide: Add chapter for nightly formatting Co-authored-by: Michael Goulet --- src/doc/style-guide/src/nightly.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/doc/style-guide/src/nightly.md b/src/doc/style-guide/src/nightly.md index 5a2815c71f13d..031811b0e6ff8 100644 --- a/src/doc/style-guide/src/nightly.md +++ b/src/doc/style-guide/src/nightly.md @@ -1,3 +1,5 @@ -The style guide does not prescribe formatting for nightly-only syntax. Refer to -the style team policy for nightly formatting procedure regarding breaking -formatter changes and feature stabilization. +This chapter documents style and formatting for nightly-only syntax. The rest of the style guide documents style for stable Rust syntax; nightly syntax only appears in this chapter. Each section here includes the name of the feature gate, so that searches (e.g. `git grep`) for a nightly feature in the Rust repository also turn up the style guide section. + +Style and formatting for nightly-only syntax should be removed from this chapter and integrated into the appropriate sections of the style guide at the time of stabilization. + +There is no guarantee of the stability of this chapter in contrast to the rest of the style guide. Refer to the style team policy for nightly formatting procedure regarding breaking changes to this chapter. From cde67f65573f54fa59aa954cea9b4e3504a7a8dd Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 5 Jul 2023 14:40:07 -0700 Subject: [PATCH 17/18] style-guide: Clarify grammar for small patterns (not a semantic change) The grammar as written feels ambiguous and confusing, in large part because it uses square brackets and commas in the names of non-terminals. Rewrite it to avoid symbols in the names of non-terminals, and to instead wrap terminals in backquotes. --- src/doc/style-guide/src/expressions.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index f5e37b6c46f69..a2994baaddc8d 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -752,9 +752,9 @@ not put the `if` clause on a newline. E.g., } ``` -If every clause in a pattern is *small*, but does not fit on one line, then the -pattern may be formatted across multiple lines with as many clauses per line as -possible. Again break before a `|`: +If every clause in a pattern is *small*, but the whole pattern does not fit on +one line, then the pattern may be formatted across multiple lines with as many +clauses per line as possible. Again break before a `|`: ```rust foo | bar | baz @@ -763,17 +763,18 @@ possible. Again break before a `|`: } ``` -We define a pattern clause to be *small* if it matches the following grammar: +We define a pattern clause to be *small* if it fits on a single line and +matches "small" in the following grammar: ``` -[small, ntp]: - - single token - - `&[single-line, ntp]` +small: + - smallntp + - unary tuple constructor: `(` smallntp `,` `)` + - `&` small -[small]: - - `[small, ntp]` - - unary tuple constructor `([small, ntp])` - - `&[small]` +smallntp: + - single token + - `&` smallntp ``` E.g., `&&Some(foo)` matches, `Foo(4, Bar)` does not. From 79df44ba78a10f5ca4cae70d81aa98bfb402e05a Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 5 Jul 2023 14:49:59 -0700 Subject: [PATCH 18/18] style-guide: Rename "smallntp" non-terminal to "small_no_tuple" for clarity The meaning of "smallntp" was not immediately obvious at a glance. Rename it to the self-describing "small_no_tuple" --- src/doc/style-guide/src/expressions.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index a2994baaddc8d..cb934990e9829 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -768,13 +768,13 @@ matches "small" in the following grammar: ``` small: - - smallntp - - unary tuple constructor: `(` smallntp `,` `)` + - small_no_tuple + - unary tuple constructor: `(` small_no_tuple `,` `)` - `&` small -smallntp: +small_no_tuple: - single token - - `&` smallntp + - `&` small_no_tuple ``` E.g., `&&Some(foo)` matches, `Foo(4, Bar)` does not.