diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index fb2ccefe12a18..d4407dbf7be77 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2117,9 +2117,10 @@ pub struct MacroDef { #[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic, Walkable)] pub struct EiiExternTarget { - /// path to the extern item we're targeting + /// path to the extern item we're targetting pub extern_item_path: Path, pub impl_unsafe: bool, + pub span: Span, } #[derive(Clone, Encodable, Decodable, Debug, Copy, Hash, Eq, PartialEq)] @@ -3812,19 +3813,6 @@ pub struct Fn { pub struct EiiImpl { pub node_id: NodeId, pub eii_macro_path: Path, - /// This field is an implementation detail that prevents a lot of bugs. - /// See for an example. - /// - /// The problem is, that if we generate a declaration *together* with its default, - /// we generate both a declaration and an implementation. The generated implementation - /// uses the same mechanism to register itself as a user-defined implementation would, - /// despite being invisible to users. What does happen is a name resolution step. - /// The invisible default implementation has to find the declaration. - /// Both are generated at the same time, so we can skip that name resolution step. - /// - /// This field is that shortcut: we prefill the extern target to skip a name resolution step, - /// making sure it never fails. It'd be awful UX if we fail name resolution in code invisible to the user. - pub known_eii_macro_resolution: Option, pub impl_safety: Safety, pub span: Span, pub inner_span: Span, diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 3a7308ef7c97a..f8b98a5ece40e 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -2,7 +2,7 @@ use rustc_abi::ExternAbi; use rustc_ast::visit::AssocCtxt; use rustc_ast::*; use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err}; -use rustc_hir::attrs::{AttributeKind, EiiDecl, EiiImplResolution}; +use rustc_hir::attrs::{AttributeKind, EiiDecl}; use rustc_hir::def::{DefKind, PerNS, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; use rustc_hir::{ @@ -134,56 +134,6 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn lower_eii_extern_target( - &mut self, - id: NodeId, - eii_name: Ident, - EiiExternTarget { extern_item_path, impl_unsafe }: &EiiExternTarget, - ) -> Option { - self.lower_path_simple_eii(id, extern_item_path).map(|did| EiiDecl { - eii_extern_target: did, - impl_unsafe: *impl_unsafe, - name: eii_name, - }) - } - - fn lower_eii_impl( - &mut self, - EiiImpl { - node_id, - eii_macro_path, - impl_safety, - span, - inner_span, - is_default, - known_eii_macro_resolution, - }: &EiiImpl, - ) -> hir::attrs::EiiImpl { - let resolution = if let Some(target) = known_eii_macro_resolution - && let Some(decl) = self.lower_eii_extern_target( - *node_id, - // the expect is ok here since we always generate this path in the eii macro. - eii_macro_path.segments.last().expect("at least one segment").ident, - target, - ) { - EiiImplResolution::Known(decl) - } else if let Some(macro_did) = self.lower_path_simple_eii(*node_id, eii_macro_path) { - EiiImplResolution::Macro(macro_did) - } else { - EiiImplResolution::Error( - self.dcx().span_delayed_bug(*span, "eii never resolved without errors given"), - ) - }; - - hir::attrs::EiiImpl { - span: self.lower_span(*span), - inner_span: self.lower_span(*inner_span), - impl_marked_unsafe: self.lower_safety(*impl_safety, hir::Safety::Safe).is_unsafe(), - is_default: *is_default, - resolution, - } - } - fn generate_extra_attrs_for_item_kind( &mut self, id: NodeId, @@ -193,14 +143,49 @@ impl<'hir> LoweringContext<'_, 'hir> { ItemKind::Fn(box Fn { eii_impls, .. }) if eii_impls.is_empty() => Vec::new(), ItemKind::Fn(box Fn { eii_impls, .. }) => { vec![hir::Attribute::Parsed(AttributeKind::EiiImpls( - eii_impls.iter().map(|i| self.lower_eii_impl(i)).collect(), + eii_impls + .iter() + .flat_map( + |EiiImpl { + node_id, + eii_macro_path, + impl_safety, + span, + inner_span, + is_default, + }| { + self.lower_path_simple_eii(*node_id, eii_macro_path).map(|did| { + hir::attrs::EiiImpl { + eii_macro: did, + span: self.lower_span(*span), + inner_span: self.lower_span(*inner_span), + impl_marked_unsafe: self + .lower_safety(*impl_safety, hir::Safety::Safe) + .is_unsafe(), + is_default: *is_default, + } + }) + }, + ) + .collect(), ))] } - ItemKind::MacroDef(name, MacroDef { eii_extern_target: Some(target), .. }) => self - .lower_eii_extern_target(id, *name, target) - .map(|decl| vec![hir::Attribute::Parsed(AttributeKind::EiiExternTarget(decl))]) + ItemKind::MacroDef( + _, + MacroDef { + eii_extern_target: Some(EiiExternTarget { extern_item_path, impl_unsafe, span }), + .. + }, + ) => self + .lower_path_simple_eii(id, extern_item_path) + .map(|did| { + vec![hir::Attribute::Parsed(AttributeKind::EiiExternTarget(EiiDecl { + eii_extern_target: did, + impl_unsafe: *impl_unsafe, + span: self.lower_span(*span), + }))] + }) .unwrap_or_default(), - ItemKind::ExternCrate(..) | ItemKind::Use(..) | ItemKind::Static(..) diff --git a/compiler/rustc_builtin_macros/src/eii.rs b/compiler/rustc_builtin_macros/src/eii.rs index 2d67608609e39..9049639925ddb 100644 --- a/compiler/rustc_builtin_macros/src/eii.rs +++ b/compiler/rustc_builtin_macros/src/eii.rs @@ -103,19 +103,19 @@ fn eii_( // span of the declaring item without attributes let item_span = func.sig.span; + // span of the eii attribute and the item below it, i.e. the full declaration + let decl_span = eii_attr_span.to(item_span); let foreign_item_name = func.ident; let mut return_items = Vec::new(); if func.body.is_some() { return_items.push(Box::new(generate_default_impl( - ecx, &func, impl_unsafe, macro_name, eii_attr_span, item_span, - foreign_item_name, ))) } @@ -133,6 +133,7 @@ fn eii_( macro_name, foreign_item_name, impl_unsafe, + decl_span, ))); return_items.into_iter().map(wrap_item).collect() @@ -186,13 +187,11 @@ fn filter_attrs_for_multiple_eii_attr( } fn generate_default_impl( - ecx: &mut ExtCtxt<'_>, func: &ast::Fn, impl_unsafe: bool, macro_name: Ident, eii_attr_span: Span, item_span: Span, - foreign_item_name: Ident, ) -> ast::Item { // FIXME: re-add some original attrs let attrs = ThinVec::new(); @@ -209,21 +208,6 @@ fn generate_default_impl( }, span: eii_attr_span, is_default: true, - known_eii_macro_resolution: Some(ast::EiiExternTarget { - extern_item_path: ast::Path { - span: foreign_item_name.span, - segments: thin_vec![ - ast::PathSegment { - ident: Ident::from_str_and_span("super", foreign_item_name.span,), - id: DUMMY_NODE_ID, - args: None - }, - ast::PathSegment { ident: foreign_item_name, id: DUMMY_NODE_ID, args: None }, - ], - tokens: None, - }, - impl_unsafe, - }), }); ast::Item { @@ -252,66 +236,18 @@ fn generate_default_impl( stmts: thin_vec![ast::Stmt { id: DUMMY_NODE_ID, kind: ast::StmtKind::Item(Box::new(ast::Item { - attrs: ThinVec::new(), + attrs, id: DUMMY_NODE_ID, span: item_span, vis: ast::Visibility { - span: item_span, + span: eii_attr_span, kind: ast::VisibilityKind::Inherited, tokens: None }, - kind: ItemKind::Mod( - ast::Safety::Default, - Ident::from_str_and_span("dflt", item_span), - ast::ModKind::Loaded( - thin_vec![ - Box::new(ast::Item { - attrs: thin_vec![ecx.attr_nested_word( - sym::allow, - sym::unused_imports, - item_span - ),], - id: DUMMY_NODE_ID, - span: item_span, - vis: ast::Visibility { - span: eii_attr_span, - kind: ast::VisibilityKind::Inherited, - tokens: None - }, - kind: ItemKind::Use(ast::UseTree { - prefix: ast::Path::from_ident( - Ident::from_str_and_span( - "super", item_span, - ) - ), - kind: ast::UseTreeKind::Glob, - span: item_span, - }), - tokens: None, - }), - Box::new(ast::Item { - attrs, - id: DUMMY_NODE_ID, - span: item_span, - vis: ast::Visibility { - span: eii_attr_span, - kind: ast::VisibilityKind::Inherited, - tokens: None - }, - kind: ItemKind::Fn(Box::new(default_func)), - tokens: None, - }), - ], - ast::Inline::Yes, - ast::ModSpans { - inner_span: item_span, - inject_use_span: item_span, - } - ) - ), + kind: ItemKind::Fn(Box::new(default_func)), tokens: None, })), - span: eii_attr_span, + span: eii_attr_span }], id: DUMMY_NODE_ID, rules: ast::BlockCheckMode::Default, @@ -416,6 +352,7 @@ fn generate_attribute_macro_to_implement( macro_name: Ident, foreign_item_name: Ident, impl_unsafe: bool, + decl_span: Span, ) -> ast::Item { let mut macro_attrs = ThinVec::new(); @@ -457,6 +394,7 @@ fn generate_attribute_macro_to_implement( eii_extern_target: Some(ast::EiiExternTarget { extern_item_path: ast::Path::from_ident(foreign_item_name), impl_unsafe, + span: decl_span, }), }, ), @@ -513,7 +451,7 @@ pub(crate) fn eii_extern_target( false }; - d.eii_extern_target = Some(EiiExternTarget { extern_item_path, impl_unsafe }); + d.eii_extern_target = Some(EiiExternTarget { extern_item_path, impl_unsafe, span }); // Return the original item and the new methods. vec![item] @@ -570,7 +508,6 @@ pub(crate) fn eii_shared_macro( impl_safety: meta_item.unsafety, span, is_default, - known_eii_macro_resolution: None, }); vec![item] diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index 1878f4043ee84..3ce28612ddfcb 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -111,7 +111,7 @@ impl CodegenCx<'_, '_> { } } - /// A definition or declaration can be assumed to be local to a group of + /// Whether a definition or declaration can be assumed to be local to a group of /// libraries that form a single DSO or executable. /// Marks the local as DSO if so. pub(crate) fn assume_dso_local(&self, llval: &llvm::Value, is_declaration: bool) -> bool { @@ -153,7 +153,7 @@ impl CodegenCx<'_, '_> { return false; } - // With pie relocation model, calls of functions defined in the translation + // With pie relocation model calls of functions defined in the translation // unit can use copy relocations. if self.tcx.sess.relocation_model() == RelocModel::Pie && !is_declaration { return true; diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 7dda824e2b18a..74f4662118b6d 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -3,9 +3,7 @@ use std::str::FromStr; use rustc_abi::{Align, ExternAbi}; use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode}; use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr}; -use rustc_hir::attrs::{ - AttributeKind, EiiImplResolution, InlineAttr, Linkage, RtsanSetting, UsedBy, -}; +use rustc_hir::attrs::{AttributeKind, InlineAttr, Linkage, RtsanSetting, UsedBy}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::{self as hir, Attribute, LangItem, find_attr, lang_items}; @@ -287,23 +285,11 @@ fn process_builtin_attrs( } AttributeKind::EiiImpls(impls) => { for i in impls { - let extern_item = match i.resolution { - EiiImplResolution::Macro(def_id) => { - let Some(extern_item) = find_attr!( - tcx.get_all_attrs(def_id), - AttributeKind::EiiExternTarget(target) => target.eii_extern_target - ) else { - tcx.dcx().span_delayed_bug( - i.span, - "resolved to something that's not an EII", - ); - continue; - }; - extern_item - } - EiiImplResolution::Known(decl) => decl.eii_extern_target, - EiiImplResolution::Error(_eg) => continue, - }; + let extern_item = find_attr!( + tcx.get_all_attrs(i.eii_macro), + AttributeKind::EiiExternTarget(target) => target.eii_extern_target + ) + .expect("eii should have declaration macro with extern target attribute"); // this is to prevent a bug where a single crate defines both the default and explicit implementation // for an EII. In that case, both of them may be part of the same final object file. I'm not 100% sure @@ -316,7 +302,7 @@ fn process_builtin_attrs( // iterate over all implementations *in the current crate* // (this is ok since we generate codegen fn attrs in the local crate) // if any of them is *not default* then don't emit the alias. - && tcx.externally_implementable_items(LOCAL_CRATE).get(&extern_item).expect("at least one").1.iter().any(|(_, imp)| !imp.is_default) + && tcx.externally_implementable_items(LOCAL_CRATE).get(&i.eii_macro).expect("at least one").1.iter().any(|(_, imp)| !imp.is_default) { continue; } diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 23201eff455fe..fa8998f0546d1 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -11,7 +11,7 @@ use rustc_error_messages::{DiagArgValue, IntoDiagArg}; use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute}; use rustc_span::def_id::DefId; use rustc_span::hygiene::Transparency; -use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol}; +use rustc_span::{Ident, Span, Symbol}; pub use rustc_target::spec::SanitizerSet; use thin_vec::ThinVec; @@ -19,22 +19,9 @@ use crate::attrs::pretty_printing::PrintAttribute; use crate::limit::Limit; use crate::{DefaultBodyStability, PartialConstStability, RustcVersion, Stability}; -#[derive(Copy, Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)] -pub enum EiiImplResolution { - /// Usually, finding the extern item that an EII implementation implements means finding - /// the defid of the associated attribute macro, and looking at *its* attributes to find - /// what foreign item its associated with. - Macro(DefId), - /// Sometimes though, we already know statically and can skip some name resolution. - /// Stored together with the eii's name for diagnostics. - Known(EiiDecl), - /// For when resolution failed, but we want to continue compilation - Error(ErrorGuaranteed), -} - #[derive(Copy, Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)] pub struct EiiImpl { - pub resolution: EiiImplResolution, + pub eii_macro: DefId, pub impl_marked_unsafe: bool, pub span: Span, pub inner_span: Span, @@ -46,7 +33,7 @@ pub struct EiiDecl { pub eii_extern_target: DefId, /// whether or not it is unsafe to implement this EII pub impl_unsafe: bool, - pub name: Ident, + pub span: Span, } #[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic, PrintAttribute)] diff --git a/compiler/rustc_hir_analysis/src/check/compare_eii.rs b/compiler/rustc_hir_analysis/src/check/compare_eii.rs index d8afee9aafc98..4e7f47a92108f 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_eii.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_eii.rs @@ -32,21 +32,21 @@ use crate::errors::{EiiWithGenerics, LifetimesOrBoundsMismatchOnEii}; pub(crate) fn compare_eii_function_types<'tcx>( tcx: TyCtxt<'tcx>, external_impl: LocalDefId, - foreign_item: DefId, + declaration: DefId, eii_name: Symbol, eii_attr_span: Span, ) -> Result<(), ErrorGuaranteed> { - check_is_structurally_compatible(tcx, external_impl, foreign_item, eii_name, eii_attr_span)?; + check_is_structurally_compatible(tcx, external_impl, declaration, eii_name, eii_attr_span)?; let external_impl_span = tcx.def_span(external_impl); let cause = ObligationCause::new( external_impl_span, external_impl, - ObligationCauseCode::CompareEii { external_impl, declaration: foreign_item }, + ObligationCauseCode::CompareEii { external_impl, declaration }, ); // FIXME(eii): even if we don't support generic functions, we should support explicit outlive bounds here - let param_env = tcx.param_env(foreign_item); + let param_env = tcx.param_env(declaration); let infcx = &tcx.infer_ctxt().build(TypingMode::non_body_analysis()); let ocx = ObligationCtxt::new_with_diagnostics(infcx); @@ -62,7 +62,7 @@ pub(crate) fn compare_eii_function_types<'tcx>( let mut wf_tys = FxIndexSet::default(); let norm_cause = ObligationCause::misc(external_impl_span, external_impl); - let declaration_sig = tcx.fn_sig(foreign_item).instantiate_identity(); + let declaration_sig = tcx.fn_sig(declaration).instantiate_identity(); let declaration_sig = tcx.liberate_late_bound_regions(external_impl.into(), declaration_sig); debug!(?declaration_sig); @@ -103,7 +103,7 @@ pub(crate) fn compare_eii_function_types<'tcx>( cause, param_env, terr, - (foreign_item, declaration_sig), + (declaration, declaration_sig), (external_impl, external_impl_sig), eii_attr_span, eii_name, diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 7ec4110f80b90..725294dfd3771 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -6,7 +6,7 @@ use rustc_abi::{ExternAbi, ScalableElt}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err}; -use rustc_hir::attrs::{AttributeKind, EiiDecl, EiiImpl, EiiImplResolution}; +use rustc_hir::attrs::{AttributeKind, EiiDecl, EiiImpl}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; @@ -1196,28 +1196,27 @@ fn check_item_fn( fn check_eiis(tcx: TyCtxt<'_>, def_id: LocalDefId) { // does the function have an EiiImpl attribute? that contains the defid of a *macro* // that was used to mark the implementation. This is a two step process. - for EiiImpl { resolution, span, .. } in + for EiiImpl { eii_macro, span, .. } in find_attr!(tcx.get_all_attrs(def_id), AttributeKind::EiiImpls(impls) => impls) .into_iter() .flatten() { - let (foreign_item, name) = match resolution { - EiiImplResolution::Macro(def_id) => { - // we expect this macro to have the `EiiMacroFor` attribute, that points to a function - // signature that we'd like to compare the function we're currently checking with - if let Some(foreign_item) = find_attr!(tcx.get_all_attrs(*def_id), AttributeKind::EiiExternTarget(EiiDecl {eii_extern_target: t, ..}) => *t) - { - (foreign_item, tcx.item_name(*def_id)) - } else { - tcx.dcx().span_delayed_bug(*span, "resolved to something that's not an EII"); - continue; - } - } - EiiImplResolution::Known(decl) => (decl.eii_extern_target, decl.name.name), - EiiImplResolution::Error(_eg) => continue, - }; - - let _ = compare_eii_function_types(tcx, def_id, foreign_item, name, *span); + // we expect this macro to have the `EiiMacroFor` attribute, that points to a function + // signature that we'd like to compare the function we're currently checking with + if let Some(eii_extern_target) = find_attr!(tcx.get_all_attrs(*eii_macro), AttributeKind::EiiExternTarget(EiiDecl {eii_extern_target, ..}) => *eii_extern_target) + { + let _ = compare_eii_function_types( + tcx, + def_id, + eii_extern_target, + tcx.item_name(*eii_macro), + *span, + ); + } else { + panic!( + "EII impl macro {eii_macro:?} did not have an eii extern target attribute pointing to a foreign function" + ) + } } } diff --git a/compiler/rustc_metadata/src/eii.rs b/compiler/rustc_metadata/src/eii.rs index b06ac84813975..5558ff9308512 100644 --- a/compiler/rustc_metadata/src/eii.rs +++ b/compiler/rustc_metadata/src/eii.rs @@ -1,5 +1,5 @@ use rustc_data_structures::fx::FxIndexMap; -use rustc_hir::attrs::{AttributeKind, EiiDecl, EiiImpl, EiiImplResolution}; +use rustc_hir::attrs::{AttributeKind, EiiDecl, EiiImpl}; use rustc_hir::def_id::DefId; use rustc_hir::find_attr; use rustc_middle::query::LocalCrate; @@ -9,7 +9,7 @@ use rustc_middle::ty::TyCtxt; pub(crate) type EiiMapEncodedKeyValue = (DefId, (EiiDecl, Vec<(DefId, EiiImpl)>)); pub(crate) type EiiMap = FxIndexMap< - DefId, // the defid of the foreign item associated with the eii + DefId, // the defid of the macro that declared the eii ( // the corresponding declaration EiiDecl, @@ -28,34 +28,18 @@ pub(crate) fn collect<'tcx>(tcx: TyCtxt<'tcx>, LocalCrate: LocalCrate) -> EiiMap for i in find_attr!(tcx.get_all_attrs(id), AttributeKind::EiiImpls(e) => e).into_iter().flatten() { - let decl = match i.resolution { - EiiImplResolution::Macro(macro_defid) => { + eiis.entry(i.eii_macro) + .or_insert_with(|| { // find the decl for this one if it wasn't in yet (maybe it's from the local crate? not very useful but not illegal) - let Some(decl) = find_attr!(tcx.get_all_attrs(macro_defid), AttributeKind::EiiExternTarget(d) => *d) - else { - // skip if it doesn't have eii_extern_target (if we resolved to another macro that's not an EII) - tcx.dcx() - .span_delayed_bug(i.span, "resolved to something that's not an EII"); - continue; - }; - decl - } - EiiImplResolution::Known(decl) => decl, - EiiImplResolution::Error(_eg) => continue, - }; - - // FIXME(eii) remove extern target from encoded decl - eiis.entry(decl.eii_extern_target) - .or_insert_with(|| (decl, Default::default())) - .1 - .insert(id.into(), *i); + (find_attr!(tcx.get_all_attrs(i.eii_macro), AttributeKind::EiiExternTarget(d) => *d).unwrap(), Default::default()) + }).1.insert(id.into(), *i); } // if we find a new declaration, add it to the list without a known implementation if let Some(decl) = find_attr!(tcx.get_all_attrs(id), AttributeKind::EiiExternTarget(d) => *d) { - eiis.entry(decl.eii_extern_target).or_insert((decl, Default::default())); + eiis.entry(id.into()).or_insert((decl, Default::default())); } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index eedb88783ec0e..c85327dc3db19 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1657,14 +1657,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { empty_proc_macro!(self); let externally_implementable_items = self.tcx.externally_implementable_items(LOCAL_CRATE); - self.lazy_array(externally_implementable_items.iter().map( - |(foreign_item, (decl, impls))| { - ( - *foreign_item, - (decl.clone(), impls.iter().map(|(impl_did, i)| (*impl_did, *i)).collect()), - ) - }, - )) + self.lazy_array(externally_implementable_items.iter().map(|(decl_did, (decl, impls))| { + (*decl_did, (decl.clone(), impls.iter().map(|(impl_did, i)| (*impl_did, *i)).collect())) + })) } #[instrument(level = "trace", skip(self))] diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs index 21a6c4d653bc5..ee21d4fbceadc 100644 --- a/compiler/rustc_mir_transform/src/errors.rs +++ b/compiler/rustc_mir_transform/src/errors.rs @@ -19,14 +19,14 @@ pub(crate) fn emit_inline_always_target_feature_diagnostic<'a, 'tcx>( caller_def_id: DefId, callee_only: &[&'a str], ) { + let callee = tcx.def_path_str(callee_def_id); + let caller = tcx.def_path_str(caller_def_id); + tcx.node_span_lint( lint::builtin::INLINE_ALWAYS_MISMATCHING_TARGET_FEATURES, tcx.local_def_id_to_hir_id(caller_def_id.as_local().unwrap()), call_span, |lint| { - let callee = tcx.def_path_str(callee_def_id); - let caller = tcx.def_path_str(caller_def_id); - lint.primary_message(format!( "call to `#[inline(always)]`-annotated `{callee}` \ requires the same target features to be inlined" diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 2d3c5c7e48a0b..f1cbb72554d2f 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -21,8 +21,8 @@ use rustc_feature::{ BuiltinAttribute, }; use rustc_hir::attrs::{ - AttributeKind, DocAttribute, DocInline, EiiDecl, EiiImpl, EiiImplResolution, InlineAttr, - MirDialect, MirPhase, ReprAttr, SanitizerSet, + AttributeKind, DocAttribute, DocInline, EiiDecl, EiiImpl, InlineAttr, MirDialect, MirPhase, + ReprAttr, SanitizerSet, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalModDefId; @@ -506,7 +506,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } fn check_eii_impl(&self, impls: &[EiiImpl], target: Target) { - for EiiImpl { span, inner_span, resolution, impl_marked_unsafe, is_default: _ } in impls { + for EiiImpl { span, inner_span, eii_macro, impl_marked_unsafe, is_default: _ } in impls { match target { Target::Fn => {} _ => { @@ -514,8 +514,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - if let EiiImplResolution::Macro(eii_macro) = resolution - && find_attr!(self.tcx.get_all_attrs(*eii_macro), AttributeKind::EiiExternTarget(EiiDecl { impl_unsafe, .. }) if *impl_unsafe) + if find_attr!(self.tcx.get_all_attrs(*eii_macro), AttributeKind::EiiExternTarget(EiiDecl { impl_unsafe, .. }) if *impl_unsafe) && !impl_marked_unsafe { self.dcx().emit_err(errors::EiiImplRequiresUnsafe { @@ -759,14 +758,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { if let Some(impls) = find_attr!(attrs, AttributeKind::EiiImpls(impls) => impls) { let sig = self.tcx.hir_node(hir_id).fn_sig().unwrap(); for i in impls { - let name = match i.resolution { - EiiImplResolution::Macro(def_id) => self.tcx.item_name(def_id), - EiiImplResolution::Known(decl) => decl.name.name, - EiiImplResolution::Error(_eg) => continue, - }; self.dcx().emit_err(errors::EiiWithTrackCaller { attr_span, - name, + name: self.tcx.item_name(i.eii_macro), sig_span: sig.span, }); } diff --git a/compiler/rustc_passes/src/eii.rs b/compiler/rustc_passes/src/eii.rs index f3e84665f21dc..ab3f9f0d21825 100644 --- a/compiler/rustc_passes/src/eii.rs +++ b/compiler/rustc_passes/src/eii.rs @@ -81,7 +81,7 @@ pub(crate) fn check_externally_implementable_items<'tcx>(tcx: TyCtxt<'tcx>, (): } // now we have all eiis! For each of them, choose one we want to actually generate. - for (foreign_item, FoundEii { decl, decl_crate, impls }) in eiis { + for (decl_did, FoundEii { decl, decl_crate, impls }) in eiis { let mut default_impls = Vec::new(); let mut explicit_impls = Vec::new(); @@ -97,7 +97,7 @@ pub(crate) fn check_externally_implementable_items<'tcx>(tcx: TyCtxt<'tcx>, (): // is instantly an error. if explicit_impls.len() > 1 { tcx.dcx().emit_err(DuplicateEiiImpls { - name: decl.name.name, + name: tcx.item_name(decl_did), first_span: tcx.def_span(explicit_impls[0].0), first_crate: tcx.crate_name(explicit_impls[0].1), second_span: tcx.def_span(explicit_impls[1].0), @@ -116,7 +116,7 @@ pub(crate) fn check_externally_implementable_items<'tcx>(tcx: TyCtxt<'tcx>, (): } if default_impls.len() > 1 { - let decl_span = tcx.def_ident_span(foreign_item).unwrap(); + let decl_span = tcx.def_ident_span(decl_did).unwrap(); tcx.dcx().span_delayed_bug(decl_span, "multiple not supported right now"); } @@ -139,9 +139,8 @@ pub(crate) fn check_externally_implementable_items<'tcx>(tcx: TyCtxt<'tcx>, (): tcx.dcx().emit_err(EiiWithoutImpl { current_crate_name: tcx.crate_name(LOCAL_CRATE), decl_crate_name: tcx.crate_name(decl_crate), - // FIXME: shouldn't call `item_name` - name: decl.name.name, - span: decl.name.span, + name: tcx.item_name(decl_did), + span: decl.span, help: (), }); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 32cf57af2e7f5..b4941a6f5b999 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1069,20 +1069,8 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc debug!("(resolving function) entering function"); if let FnKind::Fn(_, _, f) = fn_kind { - for EiiImpl { node_id, eii_macro_path, known_eii_macro_resolution, .. } in &f.eii_impls - { - // See docs on the `known_eii_macro_resolution` field: - // if we already know the resolution statically, don't bother resolving it. - if let Some(target) = known_eii_macro_resolution { - self.smart_resolve_path( - *node_id, - &None, - &target.extern_item_path, - PathSource::Expr(None), - ); - } else { - self.smart_resolve_path(*node_id, &None, &eii_macro_path, PathSource::Macro); - } + for EiiImpl { node_id, eii_macro_path, .. } in &f.eii_impls { + self.smart_resolve_path(*node_id, &None, &eii_macro_path, PathSource::Macro); } } @@ -2929,7 +2917,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.parent_scope.macro_rules = self.r.macro_rules_scopes[&def_id]; } - if let Some(EiiExternTarget { extern_item_path, impl_unsafe: _ }) = + if let Some(EiiExternTarget { extern_item_path, impl_unsafe: _, span: _ }) = ¯o_def.eii_extern_target { self.smart_resolve_path( diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index a0ccf8d7e7986..484e626d4638a 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -81,7 +81,7 @@ impl fmt::Display for CrateNum { /// because it depends on the set of crates in the entire crate graph of a /// compilation session. Again, using the same crate with a different version /// number would fix the issue with a high probability -- but that might be -/// easier said than done if the crates in questions are dependencies of +/// easier said then done if the crates in questions are dependencies of /// third-party crates. /// /// That being said, given a high quality hash function, the collision diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index c7fdc2054f712..db01cebe5b27a 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -21,8 +21,6 @@ #![feature(binary_heap_into_iter_sorted)] #![feature(binary_heap_drain_sorted)] #![feature(slice_ptr_get)] -#![feature(slice_range)] -#![feature(slice_partial_sort_unstable)] #![feature(inplace_iteration)] #![feature(iter_advance_by)] #![feature(iter_next_chunk)] diff --git a/library/alloctests/tests/sort/mod.rs b/library/alloctests/tests/sort/mod.rs index e2e141a02b597..0e2494ca9d34e 100644 --- a/library/alloctests/tests/sort/mod.rs +++ b/library/alloctests/tests/sort/mod.rs @@ -12,7 +12,6 @@ pub trait Sort { mod ffi_types; mod known_good_stable_sort; -mod partial; mod patterns; mod tests; mod zipf; diff --git a/library/alloctests/tests/sort/partial.rs b/library/alloctests/tests/sort/partial.rs deleted file mode 100644 index c7248990c70cd..0000000000000 --- a/library/alloctests/tests/sort/partial.rs +++ /dev/null @@ -1,84 +0,0 @@ -use std::fmt::Debug; -use std::ops::{Range, RangeBounds}; -use std::slice; - -use super::patterns; - -fn check_is_partial_sorted>(v: &mut [T], range: R) { - let Range { start, end } = slice::range(range, ..v.len()); - v.partial_sort_unstable(start..end); - - let max_before = v[..start].iter().max().into_iter(); - let sorted_range = v[start..end].into_iter(); - let min_after = v[end..].iter().min().into_iter(); - let seq = max_before.chain(sorted_range).chain(min_after); - assert!(seq.is_sorted()); -} - -fn check_is_partial_sorted_ranges(v: &[T]) { - let len = v.len(); - - check_is_partial_sorted::(&mut v.to_vec(), ..); - check_is_partial_sorted::(&mut v.to_vec(), 0..0); - check_is_partial_sorted::(&mut v.to_vec(), len..len); - - if len > 0 { - check_is_partial_sorted::(&mut v.to_vec(), len - 1..len - 1); - check_is_partial_sorted::(&mut v.to_vec(), 0..1); - check_is_partial_sorted::(&mut v.to_vec(), len - 1..len); - - for mid in 1..len { - check_is_partial_sorted::(&mut v.to_vec(), 0..mid); - check_is_partial_sorted::(&mut v.to_vec(), mid..len); - check_is_partial_sorted::(&mut v.to_vec(), mid..mid); - check_is_partial_sorted::(&mut v.to_vec(), mid - 1..mid + 1); - check_is_partial_sorted::(&mut v.to_vec(), mid - 1..mid); - check_is_partial_sorted::(&mut v.to_vec(), mid..mid + 1); - } - - let quarters = [0, len / 4, len / 2, (3 * len) / 4, len]; - for &start in &quarters { - for &end in &quarters { - if start < end { - check_is_partial_sorted::(&mut v.to_vec(), start..end); - } - } - } - } -} - -#[test] -fn basic_impl() { - check_is_partial_sorted::(&mut [], ..); - check_is_partial_sorted::<(), _>(&mut [], ..); - check_is_partial_sorted::<(), _>(&mut [()], ..); - check_is_partial_sorted::<(), _>(&mut [(), ()], ..); - check_is_partial_sorted::<(), _>(&mut [(), (), ()], ..); - check_is_partial_sorted::(&mut [], ..); - - check_is_partial_sorted::(&mut [77], ..); - check_is_partial_sorted::(&mut [2, 3], ..); - check_is_partial_sorted::(&mut [2, 3, 6], ..); - check_is_partial_sorted::(&mut [2, 3, 99, 6], ..); - check_is_partial_sorted::(&mut [2, 7709, 400, 90932], ..); - check_is_partial_sorted::(&mut [15, -1, 3, -1, -3, -1, 7], ..); - - check_is_partial_sorted::(&mut [15, -1, 3, -1, -3, -1, 7], 0..0); - check_is_partial_sorted::(&mut [15, -1, 3, -1, -3, -1, 7], 0..1); - check_is_partial_sorted::(&mut [15, -1, 3, -1, -3, -1, 7], 0..5); - check_is_partial_sorted::(&mut [15, -1, 3, -1, -3, -1, 7], 0..7); - check_is_partial_sorted::(&mut [15, -1, 3, -1, -3, -1, 7], 7..7); - check_is_partial_sorted::(&mut [15, -1, 3, -1, -3, -1, 7], 6..7); - check_is_partial_sorted::(&mut [15, -1, 3, -1, -3, -1, 7], 5..7); - check_is_partial_sorted::(&mut [15, -1, 3, -1, -3, -1, 7], 5..5); - check_is_partial_sorted::(&mut [15, -1, 3, -1, -3, -1, 7], 4..5); - check_is_partial_sorted::(&mut [15, -1, 3, -1, -3, -1, 7], 4..6); -} - -#[test] -fn random_patterns() { - check_is_partial_sorted_ranges(&patterns::random(10)); - check_is_partial_sorted_ranges(&patterns::random(50)); - check_is_partial_sorted_ranges(&patterns::random(100)); - check_is_partial_sorted_ranges(&patterns::random(1000)); -} diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 8113e1824f27d..1bca13b14ed4c 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -3244,219 +3244,6 @@ impl [T] { sort::unstable::sort(self, &mut |a, b| f(a).lt(&f(b))); } - /// Partially sorts the slice in ascending order **without** preserving the initial order of equal elements. - /// - /// Upon completion, for the specified range `start..end`, it's guaranteed that: - /// - /// 1. Every element in `self[..start]` is smaller than or equal to - /// 2. Every element in `self[start..end]`, which is sorted, and smaller than or equal to - /// 3. Every element in `self[end..]`. - /// - /// This partial sort is unstable, meaning it may reorder equal elements in the specified range. - /// It may reorder elements outside the specified range as well, but the guarantees above still hold. - /// - /// This partial sort is in-place (i.e., does not allocate), and *O*(*n* + *k* \* log(*k*)) worst-case, - /// where *n* is the length of the slice and *k* is the length of the specified range. - /// - /// See the documentation of [`sort_unstable`] for implementation notes. - /// - /// # Panics - /// - /// May panic if the implementation of [`Ord`] for `T` does not implement a total order, or if - /// the [`Ord`] implementation panics, or if the specified range is out of bounds. - /// - /// # Examples - /// - /// ``` - /// #![feature(slice_partial_sort_unstable)] - /// - /// let mut v = [4, -5, 1, -3, 2]; - /// - /// // empty range at the beginning, nothing changed - /// v.partial_sort_unstable(0..0); - /// assert_eq!(v, [4, -5, 1, -3, 2]); - /// - /// // empty range in the middle, partitioning the slice - /// v.partial_sort_unstable(2..2); - /// for i in 0..2 { - /// assert!(v[i] <= v[2]); - /// } - /// for i in 3..v.len() { - /// assert!(v[2] <= v[i]); - /// } - /// - /// // single element range, same as select_nth_unstable - /// v.partial_sort_unstable(2..3); - /// for i in 0..2 { - /// assert!(v[i] <= v[2]); - /// } - /// for i in 3..v.len() { - /// assert!(v[2] <= v[i]); - /// } - /// - /// // partial sort a subrange - /// v.partial_sort_unstable(1..4); - /// assert_eq!(&v[1..4], [-3, 1, 2]); - /// - /// // partial sort the whole range, same as sort_unstable - /// v.partial_sort_unstable(..); - /// assert_eq!(v, [-5, -3, 1, 2, 4]); - /// ``` - /// - /// [`sort_unstable`]: slice::sort_unstable - #[unstable(feature = "slice_partial_sort_unstable", issue = "149046")] - #[inline] - pub fn partial_sort_unstable(&mut self, range: R) - where - T: Ord, - R: RangeBounds, - { - sort::unstable::partial_sort(self, range, T::lt); - } - - /// Partially sorts the slice in ascending order with a comparison function, **without** - /// preserving the initial order of equal elements. - /// - /// Upon completion, for the specified range `start..end`, it's guaranteed that: - /// - /// 1. Every element in `self[..start]` is smaller than or equal to - /// 2. Every element in `self[start..end]`, which is sorted, and smaller than or equal to - /// 3. Every element in `self[end..]`. - /// - /// This partial sort is unstable, meaning it may reorder equal elements in the specified range. - /// It may reorder elements outside the specified range as well, but the guarantees above still hold. - /// - /// This partial sort is in-place (i.e., does not allocate), and *O*(*n* + *k* \* log(*k*)) worst-case, - /// where *n* is the length of the slice and *k* is the length of the specified range. - /// - /// See the documentation of [`sort_unstable_by`] for implementation notes. - /// - /// # Panics - /// - /// May panic if the `compare` does not implement a total order, or if - /// the `compare` itself panics, or if the specified range is out of bounds. - /// - /// # Examples - /// - /// ``` - /// #![feature(slice_partial_sort_unstable)] - /// - /// let mut v = [4, -5, 1, -3, 2]; - /// - /// // empty range at the beginning, nothing changed - /// v.partial_sort_unstable_by(0..0, |a, b| b.cmp(a)); - /// assert_eq!(v, [4, -5, 1, -3, 2]); - /// - /// // empty range in the middle, partitioning the slice - /// v.partial_sort_unstable_by(2..2, |a, b| b.cmp(a)); - /// for i in 0..2 { - /// assert!(v[i] >= v[2]); - /// } - /// for i in 3..v.len() { - /// assert!(v[2] >= v[i]); - /// } - /// - /// // single element range, same as select_nth_unstable - /// v.partial_sort_unstable_by(2..3, |a, b| b.cmp(a)); - /// for i in 0..2 { - /// assert!(v[i] >= v[2]); - /// } - /// for i in 3..v.len() { - /// assert!(v[2] >= v[i]); - /// } - /// - /// // partial sort a subrange - /// v.partial_sort_unstable_by(1..4, |a, b| b.cmp(a)); - /// assert_eq!(&v[1..4], [2, 1, -3]); - /// - /// // partial sort the whole range, same as sort_unstable - /// v.partial_sort_unstable_by(.., |a, b| b.cmp(a)); - /// assert_eq!(v, [4, 2, 1, -3, -5]); - /// ``` - /// - /// [`sort_unstable_by`]: slice::sort_unstable_by - #[unstable(feature = "slice_partial_sort_unstable", issue = "149046")] - #[inline] - pub fn partial_sort_unstable_by(&mut self, range: R, mut compare: F) - where - F: FnMut(&T, &T) -> Ordering, - R: RangeBounds, - { - sort::unstable::partial_sort(self, range, |a, b| compare(a, b) == Less); - } - - /// Partially sorts the slice in ascending order with a key extraction function, **without** - /// preserving the initial order of equal elements. - /// - /// Upon completion, for the specified range `start..end`, it's guaranteed that: - /// - /// 1. Every element in `self[..start]` is smaller than or equal to - /// 2. Every element in `self[start..end]`, which is sorted, and smaller than or equal to - /// 3. Every element in `self[end..]`. - /// - /// This partial sort is unstable, meaning it may reorder equal elements in the specified range. - /// It may reorder elements outside the specified range as well, but the guarantees above still hold. - /// - /// This partial sort is in-place (i.e., does not allocate), and *O*(*n* + *k* \* log(*k*)) worst-case, - /// where *n* is the length of the slice and *k* is the length of the specified range. - /// - /// See the documentation of [`sort_unstable_by_key`] for implementation notes. - /// - /// # Panics - /// - /// May panic if the implementation of [`Ord`] for `K` does not implement a total order, or if - /// the [`Ord`] implementation panics, or if the specified range is out of bounds. - /// - /// # Examples - /// - /// ``` - /// #![feature(slice_partial_sort_unstable)] - /// - /// let mut v = [4i32, -5, 1, -3, 2]; - /// - /// // empty range at the beginning, nothing changed - /// v.partial_sort_unstable_by_key(0..0, |k| k.abs()); - /// assert_eq!(v, [4, -5, 1, -3, 2]); - /// - /// // empty range in the middle, partitioning the slice - /// v.partial_sort_unstable_by_key(2..2, |k| k.abs()); - /// for i in 0..2 { - /// assert!(v[i].abs() <= v[2].abs()); - /// } - /// for i in 3..v.len() { - /// assert!(v[2].abs() <= v[i].abs()); - /// } - /// - /// // single element range, same as select_nth_unstable - /// v.partial_sort_unstable_by_key(2..3, |k| k.abs()); - /// for i in 0..2 { - /// assert!(v[i].abs() <= v[2].abs()); - /// } - /// for i in 3..v.len() { - /// assert!(v[2].abs() <= v[i].abs()); - /// } - /// - /// // partial sort a subrange - /// v.partial_sort_unstable_by_key(1..4, |k| k.abs()); - /// assert_eq!(&v[1..4], [2, -3, 4]); - /// - /// // partial sort the whole range, same as sort_unstable - /// v.partial_sort_unstable_by_key(.., |k| k.abs()); - /// assert_eq!(v, [1, 2, -3, 4, -5]); - /// ``` - /// - /// [`sort_unstable_by_key`]: slice::sort_unstable_by_key - #[unstable(feature = "slice_partial_sort_unstable", issue = "149046")] - #[inline] - pub fn partial_sort_unstable_by_key(&mut self, range: R, mut f: F) - where - F: FnMut(&T) -> K, - K: Ord, - R: RangeBounds, - { - sort::unstable::partial_sort(self, range, |a, b| f(a).lt(&f(b))); - } - /// Reorders the slice such that the element at `index` is at a sort-order position. All /// elements before `index` will be `<=` to this value, and all elements after will be `>=` to /// it. diff --git a/library/core/src/slice/sort/unstable/mod.rs b/library/core/src/slice/sort/unstable/mod.rs index 7ca95a3b1b198..d4df8d3a264db 100644 --- a/library/core/src/slice/sort/unstable/mod.rs +++ b/library/core/src/slice/sort/unstable/mod.rs @@ -1,13 +1,11 @@ //! This module contains the entry points for `slice::sort_unstable`. use crate::mem::SizedTypeProperties; -use crate::ops::{Range, RangeBounds}; -use crate::slice::sort::select::partition_at_index; #[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))] use crate::slice::sort::shared::find_existing_run; #[cfg(not(any(feature = "optimize_for_size", target_pointer_width = "16")))] use crate::slice::sort::shared::smallsort::insertion_sort_shift_left; -use crate::{cfg_select, intrinsics, slice}; +use crate::{cfg_select, intrinsics}; pub(crate) mod heapsort; pub(crate) mod quicksort; @@ -19,10 +17,7 @@ pub(crate) mod quicksort; /// Upholds all safety properties outlined here: /// #[inline(always)] -pub fn sort(v: &mut [T], is_less: &mut F) -where - F: FnMut(&T, &T) -> bool, -{ +pub fn sort bool>(v: &mut [T], is_less: &mut F) { // Arrays of zero-sized types are always all-equal, and thus sorted. if T::IS_ZST { return; @@ -57,54 +52,6 @@ where } } -/// Unstable partial sort the range `start..end`, after which it's guaranteed that: -/// -/// 1. Every element in `v[..start]` is smaller than or equal to -/// 2. Every element in `v[start..end]`, which is sorted, and smaller than or equal to -/// 3. Every element in `v[end..]`. -#[inline] -pub fn partial_sort(v: &mut [T], range: R, mut is_less: F) -where - F: FnMut(&T, &T) -> bool, - R: RangeBounds, -{ - // Arrays of zero-sized types are always all-equal, and thus sorted. - if T::IS_ZST { - return; - } - - let len = v.len(); - let Range { start, end } = slice::range(range, ..len); - - if end - start <= 1 { - // Empty range or single element. This case can be resolved in at most - // single partition_at_index call, without further sorting. - - if end == 0 || start == len { - // Do nothing if it is an empty range at start or end: all guarantees - // are already upheld. - return; - } - - partition_at_index(v, start, &mut is_less); - return; - } - - // A heuristic factor to decide whether to partition the slice or not. - // If the range bound is close to the edges of the slice, it's not worth - // partitioning first. - const PARTITION_THRESHOLD: usize = 8; - let mut v = v; - if end + PARTITION_THRESHOLD <= len { - v = partition_at_index(v, end - 1, &mut is_less).0; - } - if start >= PARTITION_THRESHOLD { - v = partition_at_index(v, start, &mut is_less).2; - } - - sort(v, &mut is_less); -} - /// See [`sort`] /// /// Deliberately don't inline the main sorting routine entrypoint to ensure the diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs index fcf21d9e97318..b1e5f33b1b22e 100644 --- a/library/std/src/sys/fs/uefi.rs +++ b/library/std/src/sys/fs/uefi.rs @@ -320,8 +320,8 @@ impl File { self.0.set_file_info(file_info) } - pub fn read(&self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) + pub fn read(&self, _buf: &mut [u8]) -> io::Result { + unsupported() } pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { @@ -364,7 +364,7 @@ impl File { } pub fn tell(&self) -> io::Result { - self.0.position() + unsupported() } pub fn duplicate(&self) -> io::Result { @@ -666,19 +666,6 @@ mod uefi_fs { Ok(p) } - pub(crate) fn read(&self, buf: &mut [u8]) -> io::Result { - let file_ptr = self.protocol.as_ptr(); - let mut buf_size = buf.len(); - - let r = unsafe { ((*file_ptr).read)(file_ptr, &mut buf_size, buf.as_mut_ptr().cast()) }; - - if buf_size == 0 && r.is_error() { - Err(io::Error::from_raw_os_error(r.as_usize())) - } else { - Ok(buf_size) - } - } - pub(crate) fn read_dir_entry(&self) -> io::Result>> { let file_ptr = self.protocol.as_ptr(); let mut buf_size = 0; @@ -747,14 +734,6 @@ mod uefi_fs { if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) } } - pub(crate) fn position(&self) -> io::Result { - let file_ptr = self.protocol.as_ptr(); - let mut pos = 0; - - let r = unsafe { ((*file_ptr).get_position)(file_ptr, &mut pos) }; - if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(pos) } - } - pub(crate) fn delete(self) -> io::Result<()> { let file_ptr = self.protocol.as_ptr(); let r = unsafe { ((*file_ptr).delete)(file_ptr) }; diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index bb2ee6ae10ed4..327b0eb7468a1 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -2296,7 +2296,7 @@ fn open_to_and_set_permissions( _reader_metadata: &crate::fs::Metadata, ) -> io::Result<(crate::fs::File, crate::fs::Metadata)> { use crate::fs::OpenOptions; - let writer = OpenOptions::new().write(true).create(true).truncate(true).open(to)?; + let writer = OpenOptions::new().open(to)?; let writer_metadata = writer.metadata()?; Ok((writer, writer_metadata)) } diff --git a/src/tools/tidy/src/triagebot.rs b/src/tools/tidy/src/triagebot.rs index a74d980cfcb7f..59cd9d80b07ac 100644 --- a/src/tools/tidy/src/triagebot.rs +++ b/src/tools/tidy/src/triagebot.rs @@ -2,22 +2,11 @@ use std::collections::HashSet; use std::path::Path; -use std::sync::LazyLock; use toml::Value; use crate::diagnostics::TidyCtx; -static SUBMODULES: LazyLock> = LazyLock::new(|| { - // WORKSPACES doesn't list all submodules but it's contains the main at least - crate::deps::WORKSPACES - .iter() - .map(|ws| ws.submodules.iter()) - .flatten() - .map(|p| Path::new(p)) - .collect() -}); - pub fn check(path: &Path, tidy_ctx: TidyCtx) { let mut check = tidy_ctx.start_check("triagebot"); let triagebot_path = path.join("triagebot.toml"); @@ -50,13 +39,8 @@ pub fn check(path: &Path, tidy_ctx: TidyCtx) { if !full_path.exists() { // The full-path doesn't exists, maybe it's a glob, let's add it to the glob set builder // to be checked against all the file and directories in the repository. - let trimmed_path = clean_path.trim_end_matches('/'); - builder.add(globset::Glob::new(&format!("{trimmed_path}{{,/*}}")).unwrap()); + builder.add(globset::Glob::new(&format!("{clean_path}*")).unwrap()); glob_entries.push(clean_path.to_string()); - } else if is_in_submodule(Path::new(clean_path)) { - check.error(format!( - "triagebot.toml [mentions.*] '{clean_path}' cannot match inside a submodule" - )); } } @@ -65,18 +49,8 @@ pub fn check(path: &Path, tidy_ctx: TidyCtx) { let mut found = HashSet::new(); let mut matches = Vec::new(); - let cloned_path = path.to_path_buf(); - // Walk the entire repository and match any entry against the remaining paths - for entry in ignore::WalkBuilder::new(&path) - .filter_entry(move |entry| { - // Ignore entries inside submodules as triagebot cannot detect them - let entry_path = entry.path().strip_prefix(&cloned_path).unwrap(); - is_not_in_submodule(entry_path) - }) - .build() - .flatten() - { + for entry in ignore::WalkBuilder::new(path).build().flatten() { // Strip the prefix as mentions entries are always relative to the repo let entry_path = entry.path().strip_prefix(path).unwrap(); @@ -152,11 +126,3 @@ pub fn check(path: &Path, tidy_ctx: TidyCtx) { } } } - -fn is_not_in_submodule(path: &Path) -> bool { - SUBMODULES.contains(&path) || !SUBMODULES.iter().any(|p| path.starts_with(*p)) -} - -fn is_in_submodule(path: &Path) -> bool { - !SUBMODULES.contains(&path) && SUBMODULES.iter().any(|p| path.starts_with(*p)) -} diff --git a/tests/ui/eii/duplicate/eii_conflict_with_macro.rs b/tests/ui/eii/duplicate/eii_conflict_with_macro.rs deleted file mode 100644 index d8118f8417a09..0000000000000 --- a/tests/ui/eii/duplicate/eii_conflict_with_macro.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ compile-flags: --crate-type rlib -//@ build-pass -#![feature(extern_item_impls)] - -macro_rules! foo_impl { () => {} } -#[eii] -fn foo_impl() {} diff --git a/tests/ui/eii/privacy2.rs b/tests/ui/eii/privacy2.rs index a0bc26ef629b7..a4ae188bd0ec7 100644 --- a/tests/ui/eii/privacy2.rs +++ b/tests/ui/eii/privacy2.rs @@ -1,5 +1,5 @@ //@ aux-build:codegen3.rs -// Tests whether name resolution respects privacy properly. +// Tests whether name resulution respects privacy properly. #![feature(extern_item_impls)] extern crate codegen3 as codegen; diff --git a/tests/ui/eii/privacy2.stderr b/tests/ui/eii/privacy2.stderr index 903285d4d1e37..0d44604567e44 100644 --- a/tests/ui/eii/privacy2.stderr +++ b/tests/ui/eii/privacy2.stderr @@ -17,18 +17,18 @@ LL | fn decl1(x: u64); | ^^^^^^^^^^^^^^^^^ error: `#[eii2]` required, but not found - --> $DIR/auxiliary/codegen3.rs:9:7 + --> $DIR/auxiliary/codegen3.rs:9:1 | LL | #[eii(eii2)] - | ^^^^ expected because `#[eii2]` was declared here in crate `codegen3` + | ^^^^^^^^^^^^ expected because `#[eii2]` was declared here in crate `codegen3` | = help: expected at least one implementation in crate `privacy2` or any of its dependencies error: `#[eii3]` required, but not found - --> $DIR/auxiliary/codegen3.rs:13:11 + --> $DIR/auxiliary/codegen3.rs:13:5 | LL | #[eii(eii3)] - | ^^^^ expected because `#[eii3]` was declared here in crate `codegen3` + | ^^^^^^^^^^^^ expected because `#[eii3]` was declared here in crate `codegen3` | = help: expected at least one implementation in crate `privacy2` or any of its dependencies