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 8271b42da4c7..0edf848c1e60 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 6ef3418cc5f7..1883a8aa0a34 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 @@ pub fn LLVMRustGetNamedValue( 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 ea04899ab687..3a43fa415bbc 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 3783ec41b7e2..1470180dea71 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2182,7 +2182,11 @@ pub(super) fn check_fn_front_matter(&mut self, check_pub: bool, case: Case) -> b // `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 000000000000..18b502736f7b --- /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 000000000000..a0c5e665ff8f --- /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 727777333451..9af06f1a48a3 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::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 @@ 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 @@ fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> &'a NameBinding<'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 @@ pub(crate) fn define(&mut self, parent: Module<'a>, ident: Ident, ns: Namespa 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 @@ fn build_reduced_graph_for_external_crate_res(&mut self, child: &ModChild) { 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 d9e4974626d7..4db4108c6f42 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -182,13 +182,13 @@ fn report_with_use_injections(&mut self, krate: &Crate) { } } - 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 @@ pub(crate) fn report_conflict<'b>( // 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 @@ pub(crate) fn lint_if_path_starts_with_module( &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 @@ pub(crate) fn add_typo_suggestion( 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 @@ fn report_ambiguity_error(&self, ambiguity_error: &AmbiguityError<'_>) { 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 @@ fn report_ambiguity_error(&self, ambiguity_error: &AmbiguityError<'_>) { /// 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 @@ fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'a>) { 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 @@ fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'a>) { _ => 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 @@ pub(crate) fn report_path_resolution_error( 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 4863c9f47901..eb210532f51d 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -5,7 +5,6 @@ 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::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 @@ fn nearest_normal_mod(&mut self, def_id: LocalDefId) -> LocalDefId { 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 @@ fn set_bindings_effective_visibilities(&mut self, module_id: LocalDefId) { // 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 @@ fn set_bindings_effective_visibilities(&mut self, module_id: LocalDefId) { break; } - parent_id = ParentId::Import(binding_id); + parent_id = ParentId::Import(binding); binding = nested_binding; } @@ -192,7 +188,7 @@ fn may_update( } } - 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 36f01676e7e0..ba6f50ef1bae 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -284,7 +284,7 @@ pub(crate) fn resolve_ident_in_lexical_scope( 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 @@ pub(crate) fn early_resolve_ident_in_lexical_scope( 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 @@ struct Flags: u8 { // } // 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 @@ pub(crate) fn maybe_resolve_ident_in_module( 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 @@ pub(crate) fn resolve_ident_in_module( 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 @@ fn resolve_ident_in_module_ext( 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 @@ fn resolve_ident_in_module_unadjusted( 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 @@ fn resolve_ident_in_module_unadjusted_ext( 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 @@ fn resolve_ident_in_module_unadjusted_ext( // 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 @@ fn resolve_ident_in_module_unadjusted_ext( 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 @@ pub(crate) fn resolve_path( 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 @@ pub(crate) fn resolve_path_with_ribs( 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 074f761c53ba..5f5b49d8564d 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -12,7 +12,7 @@ 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 @@ pub(crate) fn import( } } - 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 @@ pub(crate) fn try_define( &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 @@ pub(crate) fn try_define( 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 @@ fn update_resolution(&mut self, module: Module<'a>, key: BindingKey, f: F) 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 @@ pub(crate) fn finalize_imports(&mut self) { 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 @@ pub(crate) fn check_hidden_glob_reexports( 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 @@ fn check_for_redundant_imports( &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 bca95ce54ad3..735a499ff68d 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1284,7 +1284,7 @@ fn resolve_ident_in_lexical_scope( 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 cc4cb9fa30cd..8fefbe8177e5 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -352,7 +352,7 @@ fn from(seg: &'a ast::PathSegment) -> 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 @@ fn new( 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// 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 @@ fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> &'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 @@ fn is_import(&self) -> bool { #[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 @@ fn macro_kind(&self) -> Option { 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 @@ fn may_appear_after( #[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 @@ fn new_module( 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 @@ pub fn new( 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 @@ fn matches_previous_ambiguity_error(&mut self, ambi: &AmbiguityError<'_>) -> boo 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 @@ fn record_use( // 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 @@ fn is_accessible_from( 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 @@ fn set_binding_parent_module(&mut self, binding: &'a NameBinding<'a>, module: Mo 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 @@ fn disambiguate_macro_rules_vs_modularized( } } - 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 d33e8d40b638..d16b7902f606 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -42,7 +42,7 @@ /// 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 @@ fn check_stability_and_deprecation( 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 9af06f1a48a3..fdf1e281b0bd 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 @@ fn add_import( 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 @@ fn add_import( 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 @@ fn build_reduced_graph_for_extern_crate( (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 @@ fn process_macro_use_imports(&mut self, item: &Item, module: Module<'a>) -> bool } 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 @@ fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'a> { 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 4db4108c6f42..9c1d42514657 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -262,7 +262,7 @@ pub(crate) fn report_conflict( // 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 @@ pub(crate) fn report_conflict( (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 @@ fn add_suggestion_for_rename_of_use( &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 @@ fn add_suggestion_for_rename_of_use( 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 @@ fn make_external_crate_suggestion( /// ``` 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 ba6f50ef1bae..40eee48e475c 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -20,7 +20,7 @@ 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 @@ fn resolve_ident_in_module_unadjusted_ext( } 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 @@ fn resolve_ident_in_module_unadjusted_ext( } 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 5f5b49d8564d..fa8c15abc4b2 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -135,7 +135,7 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { /// 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 @@ fn simplify(&self, r: &Resolver<'_, '_>) -> Reexport { 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 @@ pub(crate) fn binding(&self) -> Option> { } }) } - - 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 @@ fn update_resolution(&mut self, module: Module<'a>, key: BindingKey, f: F) 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 @@ fn update_resolution(&mut self, module: Module<'a>, key: BindingKey, f: F) // 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 @@ pub(crate) fn resolve_imports(&mut self) { 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 @@ pub(crate) fn check_hidden_glob_reexports( } } - 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 @@ fn throw_unresolved_import_error(&mut self, errors: Vec<(&Import<'_>, Unresolved /// /// 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 @@ fn resolve_import(&mut self, import: &'a Import<'a>) -> usize { } 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 @@ fn resolve_import(&mut self, import: &'a Import<'a>) -> usize { /// /// 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 @@ fn finalize_import(&mut self, import: &'a Import<'a>) -> Option, + import: Import<'a>, source_bindings: &PerNS, Determinacy>>>, target_bindings: &PerNS>>>, target: Ident, @@ -1302,7 +1293,7 @@ fn check_for_redundant_imports( } } - 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 8fefbe8177e5..8ee0c715a0ea 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -64,7 +64,7 @@ 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 @@ fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> 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 @@ fn is_possibly_imported_variant(&self) -> bool { 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 @@ fn local_modules(&'a self) -> std::cell::Ref<'a, Vec>> { 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 @@ fn find_transitive_imports( 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 @@ fn record_use(&mut self, ident: Ident, used_binding: NameBinding<'a>, is_lexical 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 fdf1e281b0bd..e6ceedddfa1b 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::Span; use std::cell::Cell; -use std::ptr; type Res = def::Res; @@ -142,8 +141,8 @@ pub(crate) fn expn_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> { 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 @@ fn build_reduced_graph_for_extern_crate( }); 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 9c1d42514657..d3dcdfa42754 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 @@ fn lookup_import_candidates_from_module( // 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 @@ fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'a>) { 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 @@ pub(crate) fn find_similarly_named_module_or_crate( 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 @@ pub(crate) fn report_path_resolution_error( } 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 @@ pub(crate) fn check_for_module_export_macro( 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 40eee48e475c..520fab1f0c83 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -11,8 +11,6 @@ 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 @@ struct Flags: u8 { ), ); } - 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 fa8c15abc4b2..036fbf2dbf0a 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -35,7 +35,7 @@ use smallvec::SmallVec; use std::cell::Cell; -use std::{mem, ptr}; +use std::mem; type Res = def::Res; @@ -463,7 +463,7 @@ pub(crate) fn resolve_imports(&mut self) { 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 @@ pub(crate) fn check_hidden_glob_reexports( 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 @@ fn finalize_import(&mut self, import: Import<'a>) -> Option { // 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 @@ fn finalize_import(&mut self, import: Import<'a>) -> Option) { 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 735a499ff68d..90cb312edd20 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2972,7 +2972,7 @@ fn check_trait_item( 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 9fec7cc3defb..c0e3f1aaf01f 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1593,7 +1593,7 @@ pub(crate) fn find_similarly_named_assoc_item( 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 8ee0c715a0ea..b6a312c2982a 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 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 @@ fn res(self) -> Res { } } -#[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 @@ fn new( 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 @@ fn for_each_child<'tcx, R, F>(&'a self, resolver: &mut R, mut f: F) } /// 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 @@ fn ensure_traits<'tcx, R>(&'a self, resolver: &mut R) } } - 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 @@ fn res(&self) -> Option { } // 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 @@ fn opt_def_id(&self) -> Option { } // `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 @@ fn nearest_item_scope(&'a self) -> Module<'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 @@ fn is_ancestor_of(&self, mut other: &Self) -> bool { } } -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 @@ fn is_extern_crate(&self) -> bool { 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 @@ fn new_module( 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 @@ fn resolutions(&mut self, module: Module<'a>) -> &'a Resolutions<'a> { 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 @@ fn is_accessible_from( 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 @@ fn disambiguate_macro_rules_vs_modularized( ) { (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 036fbf2dbf0a..d37fe783bbac 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 b6a312c2982a..da3d86a4718d 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 d511d2b1280d..29335a8c0f4c 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -367,13 +367,6 @@ pub fn advance_token(&mut self) -> Token { 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 e4b07ab8108e..3fc5fd481ea6 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 000000000000..571c319d8c53 --- /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 b27da26ed23b..ddd6d9a25daa 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 bc0c537aada8..8de36ca4a6ed 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: 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 | m!(c "test"); + | + -error: aborting due to 2 previous errors +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 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 82e8e2090d7d..066505c23dfc 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 000000000000..47361fb61d27 --- /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 | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs index f8fa81e6ef18..7b6f8810cbab 100644 --- a/library/std/src/sys/unix/args.rs +++ b/library/std/src/sys/unix/args.rs @@ -242,15 +242,13 @@ pub fn args() -> Args { 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 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() as *const libc::c_uchar); + 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 da08c018d0e3..72b9ad3480b3 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 7b6f8810cbab..eafd6821f540 100644 --- a/library/std/src/sys/unix/args.rs +++ b/library/std/src/sys/unix/args.rs @@ -242,13 +242,13 @@ pub fn args() -> Args { 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 9cf5cfcc8d55..fbc7f04ce9ae 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -1097,7 +1097,7 @@ pub fn file_attr(&self) -> io::Result { 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 1b72e21a8328..326f1481e191 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 @@ unsafe fn sanitize_standard_fds() { 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 @@ unsafe fn sanitize_standard_fds() { 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 5f316b12b625..640648e87074 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 @@ 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 @@ pub fn to_child_stdio(&self, readable: bool) -> io::Result<(ChildStdio, Option= Win10 1607 // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription @@ -354,7 +354,7 @@ pub fn WaitOnAddress( } 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 649cc4bfdbf1..4fe95d41116b 100644 --- a/library/std/src/sys/windows/compat.rs +++ b/library/std/src/sys/windows/compat.rs @@ -228,9 +228,9 @@ pub fn option() -> Option { /// 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 b11c89622032..bcc172b0fae3 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 1f6c0b75a09d..ecc84c1618c0 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -131,6 +131,7 @@ "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 cdf6a4cc2de2..54d74ab6a751 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 39ff3a0ba2d2..ad51f2d09585 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 ad0636894b79..a57508815d6f 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 94885b40cc1a..d7dd98d79389 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 998e3b300da9..0f5e975445fa 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 2f7eb08ad3d4..5b2bbdb4bde1 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -19,6 +19,8 @@ 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 @@ fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen BackendTypes for Builder<'_, 'll, 'tcx> { type Value = as BackendTypes>::Value; @@ -1002,13 +1007,14 @@ fn resume(&mut self, exn0: &'ll Value, exn1: &'ll Value) { } 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 @@ fn cleanup_ret(&mut self, funclet: &Funclet<'ll>, unwind: Option<&'ll BasicBlock } 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 @@ fn catch_switch( 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 2087754c66b8..df52f50f86f0 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -8,6 +8,7 @@ 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 @@ fn codegen_static(&self, def_id: DefId, is_mutable: bool) { .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 @@ fn codegen_static(&self, def_id: DefId, is_mutable: bool) { 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 287a22bc9a6c..e1e0a442845d 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -8,6 +8,7 @@ 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 @@ pub fn coverage_context(&self) -> Option<&coverageinfo::CrateCoverageContext<'ll } 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 8be54b7eb718..37f30917609a 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 4b88ab8a97a8..ad07d637106b 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::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 c2f16cad3fcb..0858f6b5f8eb 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -113,7 +113,7 @@ pub fn finalize(&self, sess: &Session) { 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 @@ pub fn finalize(&self, sess: &Session) { 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 24968e00cc8e..24ba28bbc82c 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 000000000000..2a4cd6004260 --- /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 6a51450a777e..0a7aff62257a 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -599,6 +599,9 @@ fn dir_is_empty(dir: &Path) -> bool { 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 000000000000..05d205266b44 --- /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 000000000000..7ea7a7b2de7b --- /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 59fe9fdc6694..606485bfb6c7 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 000000000000..5a2815c71f13 --- /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 5a2815c71f13..031811b0e6ff 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 f5e37b6c46f6..a2994baaddc8 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 a2994baaddc8..cb934990e982 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.