diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index ad5a541d3a25d..7432d9ca8749c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -161,9 +161,9 @@ impl, S: Stage> AttributeParser for Single if let Some(pa) = T::convert(cx, args) { if let Some((_, used)) = group.1 { T::ON_DUPLICATE.exec::(cx, used, cx.attr_span); + } else { + group.1 = Some((pa, cx.attr_span)); } - - group.1 = Some((pa, cx.attr_span)); } }, )]; diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 1c6889efe7501..9ec27fb175e27 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -37,9 +37,9 @@ use crate::imports::{ImportData, ImportKind, OnUnknownData}; use crate::macros::{MacroRulesDecl, MacroRulesScope, MacroRulesScopeRef}; use crate::ref_mut::CmCell; use crate::{ - BindingKey, Decl, DeclData, DeclKind, ExternPreludeEntry, Finalize, IdentKey, MacroData, - Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, Res, ResolutionError, - Resolver, Segment, Used, VisResolutionError, errors, + BindingKey, Decl, DeclData, DeclKind, ExternModule, ExternPreludeEntry, Finalize, IdentKey, + LocalModule, MacroData, Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, Res, + ResolutionError, Resolver, Segment, Used, VisResolutionError, errors, }; impl<'ra, 'tcx> Resolver<'ra, 'tcx> { @@ -62,7 +62,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Create a name definition from the given components, and put it into the local module. fn define_local( &mut self, - parent: Module<'ra>, + parent: LocalModule<'ra>, orig_ident: Ident, ns: Namespace, res: Res, @@ -70,7 +70,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { span: Span, expn_id: LocalExpnId, ) { - let decl = self.arenas.new_def_decl(res, vis.to_def_id(), span, expn_id, Some(parent)); + let decl = + self.arenas.new_def_decl(res, vis.to_def_id(), span, expn_id, Some(parent.to_module())); let ident = IdentKey::new(orig_ident); self.plant_decl_into_local_module(ident, orig_ident.span, ns, decl); } @@ -78,7 +79,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Create a name definition from the given components, and put it into the extern module. fn define_extern( &self, - parent: Module<'ra>, + parent: ExternModule<'ra>, ident: IdentKey, orig_ident_span: Span, ns: Namespace, @@ -97,7 +98,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { vis: CmCell::new(vis), span, expansion, - parent_module: Some(parent), + parent_module: Some(parent.to_module()), }); // Even if underscore names cannot be looked up, we still need to add them to modules, // because they can be fetched by glob imports from those modules, and bring traits @@ -105,7 +106,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let key = BindingKey::new_disambiguated(ident, ns, || (child_index + 1).try_into().unwrap()); // 0 indicates no underscore if self - .resolution_or_default(parent, key, orig_ident_span) + .resolution_or_default(parent.to_module(), key, orig_ident_span) .borrow_mut_unchecked() .non_glob_decl .replace(decl) @@ -149,30 +150,30 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// returns `None`. pub(crate) fn get_module(&self, def_id: DefId) -> Option> { match def_id.as_local() { - Some(local_def_id) => self.local_module_map.get(&local_def_id).copied(), + Some(local_def_id) => self.local_module_map.get(&local_def_id).map(|m| m.to_module()), None => { if let module @ Some(..) = self.extern_module_map.borrow().get(&def_id) { - return module.copied(); + return module.map(|m| m.to_module()); } // Query `def_kind` is not used because query system overhead is too expensive here. let def_kind = self.cstore().def_kind_untracked(self.tcx, def_id); if def_kind.is_module_like() { - let parent = self - .tcx - .opt_parent(def_id) - .map(|parent_id| self.get_nearest_non_block_module(parent_id)); + let parent = self.tcx.opt_parent(def_id).map(|parent_id| { + self.get_nearest_non_block_module(parent_id).expect_extern() + }); // Query `expn_that_defined` is not used because // hashing spans in its result is expensive. let expn_id = self.cstore().expn_that_defined_untracked(self.tcx, def_id); - return Some(self.new_extern_module( + let module = self.new_extern_module( parent, ModuleKind::Def(def_kind, def_id, Some(self.tcx.item_name(def_id))), expn_id, self.def_span(def_id), // FIXME: Account for `#[no_implicit_prelude]` attributes. parent.is_some_and(|module| module.no_implicit_prelude), - )); + ); + return Some(module.to_module()); } None @@ -186,13 +187,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { None => expn_id .as_local() .and_then(|expn_id| self.ast_transform_scopes.get(&expn_id).copied()) - .unwrap_or(self.graph_root), + .unwrap_or(self.graph_root) + .to_module(), } } pub(crate) fn macro_def_scope(&self, def_id: DefId) -> Module<'ra> { if let Some(id) = def_id.as_local() { - self.local_macro_def_scopes[&id] + self.local_macro_def_scopes[&id].to_module() } else { self.get_nearest_non_block_module(def_id) } @@ -246,10 +248,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { visitor.parent_scope.macro_rules } - pub(crate) fn build_reduced_graph_external(&self, module: Module<'ra>) { + pub(crate) fn build_reduced_graph_external(&self, module: ExternModule<'ra>) { let def_id = module.def_id(); let children = self.tcx.module_children(def_id); - let parent_scope = ParentScope::module(module, self.arenas); + let parent_scope = ParentScope::module(module.to_module(), self.arenas); for (i, child) in children.iter().enumerate() { self.build_reduced_graph_for_external_crate_res(child, parent_scope, i, None) } @@ -273,7 +275,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { child_index: usize, ambig_child: Option<&ModChild>, ) { - let parent = parent_scope.module; + let parent = parent_scope.module.expect_extern(); let child_span = |this: &Self, reexport_chain: &[Reexport], res: def::Res<_>| { this.def_span( reexport_chain @@ -291,7 +293,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let ModChild { ident: _, res, vis, ref reexport_chain } = *ambig_child; let span = child_span(self, reexport_chain, res); let res = res.expect_non_local(); - self.arenas.new_def_decl(res, vis, span, expansion, Some(parent)) + self.arenas.new_def_decl(res, vis, span, expansion, Some(parent.to_module())) }); // Record primary definitions. @@ -801,7 +803,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { adt_span: Span, ) { let parent_scope = &self.parent_scope; - let parent = parent_scope.module; + let parent = parent_scope.module.expect_local(); let expansion = parent_scope.expansion; // Define a name in the type namespace if it is not anonymous. @@ -817,7 +819,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { /// Constructs the reduced graph for one item. fn build_reduced_graph_for_item(&mut self, item: &'a Item) { let parent_scope = &self.parent_scope; - let parent = parent_scope.module; + let parent = parent_scope.module.expect_local(); let expansion = parent_scope.expansion; let sp = item.span; let vis = self.resolve_visibility(&item.vis); @@ -862,7 +864,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { { self.r.mods_with_parse_errors.insert(def_id); } - self.parent_scope.module = self.r.new_local_module( + let module = self.r.new_local_module( Some(parent), ModuleKind::Def(def_kind, def_id, Some(ident.name)), expansion.to_expn_id(), @@ -870,6 +872,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { parent.no_implicit_prelude || ast::attr::contains_name(&item.attrs, sym::no_implicit_prelude), ); + self.parent_scope.module = module.to_module(); } // These items live in the value namespace. @@ -895,13 +898,14 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ItemKind::Enum(ident, _, _) | ItemKind::Trait(box ast::Trait { ident, .. }) => { self.r.define_local(parent, ident, TypeNS, res, vis, sp, expansion); - self.parent_scope.module = self.r.new_local_module( + let module = self.r.new_local_module( Some(parent), ModuleKind::Def(def_kind, def_id, Some(ident.name)), expansion.to_expn_id(), item.span, parent.no_implicit_prelude, ); + self.parent_scope.module = module.to_module(); } // These items live in both the type and value namespaces. @@ -997,7 +1001,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { self.r.dcx().emit_err(errors::ExternCrateSelfRequiresRenaming { span: sp }); return; } else if orig_name == Some(kw::SelfLower) { - Some(self.r.graph_root) + Some(self.r.graph_root.to_module()) } else { let tcx = self.r.tcx; let crate_id = self.r.cstore_mut().process_extern_crate( @@ -1038,7 +1042,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { self.r.potentially_unused_imports.push(import); let import_decl = self.r.new_import_decl(decl, import); let ident = IdentKey::new(orig_ident); - if ident.name != kw::Underscore && parent == self.r.graph_root { + if ident.name != kw::Underscore && parent == self.r.graph_root.to_module() { // FIXME: this error is technically unnecessary now when extern prelude is split into // two scopes, remove it with lang team approval. if let Some(entry) = self.r.extern_prelude.get(&ident) @@ -1083,7 +1087,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { ForeignItemKind::TyAlias(..) => TypeNS, ForeignItemKind::MacCall(..) => unreachable!(), }; - let parent = self.parent_scope.module; + let parent = self.parent_scope.module.expect_local(); let expansion = self.parent_scope.expansion; let vis = self.resolve_visibility(&item.vis); self.r.define_local(parent, ident, ns, self.res(def_id), vis, item.span, expansion); @@ -1091,7 +1095,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } fn build_reduced_graph_for_block(&mut self, block: &Block) { - let parent = self.parent_scope.module; + let parent = self.parent_scope.module.expect_local(); let expansion = self.parent_scope.expansion; if self.block_needs_anonymous_module(block) { let module = self.r.new_local_module( @@ -1102,7 +1106,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { parent.no_implicit_prelude, ); self.r.block_map.insert(block.id, module); - self.parent_scope.module = module; // Descend into the block. + self.parent_scope.module = module.to_module(); // Descend into the block. } } @@ -1302,7 +1306,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { _ => unreachable!(), }; - self.r.local_macro_def_scopes.insert(def_id, parent_scope.module); + self.r.local_macro_def_scopes.insert(def_id, parent_scope.module.expect_local()); if macro_rules { let ident = IdentKey::new(orig_ident); @@ -1325,7 +1329,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { let import = self.r.arenas.alloc_import(ImportData { kind: ImportKind::MacroExport, root_id: item.id, - parent_scope: ParentScope { module: self.r.graph_root, ..parent_scope }, + parent_scope: ParentScope { + module: self.r.graph_root.to_module(), + ..parent_scope + }, imported_module: CmCell::new(None), has_attributes: false, use_span_with_attributes: span, @@ -1356,7 +1363,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { self.r.macro_rules_scopes.insert(def_id, scope); scope } else { - let module = parent_scope.module; + let module = parent_scope.module.expect_local(); let vis = match item.kind { // Visibilities must not be resolved non-speculatively twice // and we already resolved this one as a `fn` item visibility. @@ -1504,7 +1511,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { } if ctxt == AssocCtxt::Trait { - let parent = self.parent_scope.module; + let parent = self.parent_scope.module.expect_local(); let expansion = self.parent_scope.expansion; self.r.define_local(parent, ident, ns, self.res(def_id), vis, item.span, expansion); } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) @@ -1586,7 +1593,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { return; } - let parent = self.parent_scope.module; + let parent = self.parent_scope.module.expect_local(); let expn_id = self.parent_scope.expansion; let ident = variant.ident; diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index b5246808cd5ad..7e1b1bce3ff74 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -545,7 +545,7 @@ impl Resolver<'_, '_> { let unused_imports = visitor.unused_imports; let mut check_redundant_imports = FxIndexSet::default(); for module in &self.local_modules { - for (_key, resolution) in self.resolutions(*module).borrow().iter() { + for (_key, resolution) in self.resolutions(module.to_module()).borrow().iter() { if let Some(decl) = resolution.borrow().best_decl() && let DeclKind::Import { import, .. } = decl.kind && let ImportKind::Single { id, .. } = import.kind diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 08ee2db1f5b17..bf260d823b765 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1585,7 +1585,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { lookup_ident, namespace, parent_scope, - self.graph_root, + self.graph_root.to_module(), crate_path, &filter_fn, ); @@ -2074,7 +2074,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if kind != AmbiguityKind::GlobVsGlob { if let Scope::ModuleNonGlobs(module, _) | Scope::ModuleGlobs(module, _) = scope { - if module == self.graph_root { + if module == self.graph_root.to_module() { help_msgs.push(format!( "use `crate::{ident}` to refer to this {thing} unambiguously" )); @@ -2452,7 +2452,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.local_module_map .iter() .filter(|(_, module)| { - current_module.is_ancestor_of(**module) && current_module != **module + let module = module.to_module(); + current_module.is_ancestor_of(module) && current_module != module }) .flat_map(|(_, module)| module.kind.name()), ) @@ -2461,7 +2462,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .borrow() .iter() .filter(|(_, module)| { - current_module.is_ancestor_of(**module) && current_module != **module + let module = module.to_module(); + current_module.is_ancestor_of(module) && current_module != module }) .flat_map(|(_, module)| module.kind.name()), ) diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 7ff3f09668928..56a0ee2acc1a6 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -24,9 +24,9 @@ use crate::late::{ use crate::macros::{MacroRulesScope, sub_namespace_match}; use crate::{ AmbiguityError, AmbiguityKind, AmbiguityWarning, BindingKey, CmResolver, Decl, DeclKind, - Determinacy, Finalize, IdentKey, ImportKind, LateDecl, Module, ModuleKind, ModuleOrUniformRoot, - ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, Scope, ScopeSet, - Segment, Stage, Symbol, Used, errors, + Determinacy, Finalize, IdentKey, ImportKind, LateDecl, LocalModule, Module, ModuleKind, + ModuleOrUniformRoot, ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, + Scope, ScopeSet, Segment, Stage, Symbol, Used, errors, }; #[derive(Copy, Clone)] @@ -346,7 +346,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } else if let RibKind::Block(Some(module)) = rib.kind && let Ok(binding) = self.cm().resolve_ident_in_scope_set( ident, - ScopeSet::Module(ns, module), + ScopeSet::Module(ns, module.to_module()), parent_scope, finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }), ignore_decl, @@ -357,7 +357,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return Some(LateDecl::Decl(binding)); } else if let RibKind::Module(module) = rib.kind { // Encountered a module item, abandon ribs and look into that module and preludes. - let parent_scope = &ParentScope { module, ..*parent_scope }; + let parent_scope = &ParentScope { module: module.to_module(), ..*parent_scope }; let finalize = finalize.map(|f| Finalize { stage: Stage::Late, ..f }); return self .cm() @@ -658,7 +658,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ) }; let binding = self.reborrow().resolve_ident_in_module_globs_unadjusted( - module, + module.expect_local(), ident, orig_ident_span, ns, @@ -1122,7 +1122,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Attempts to resolve `ident` in namespace `ns` of glob bindings in `module`. fn resolve_ident_in_module_globs_unadjusted<'r>( mut self: CmResolver<'r, 'ra, 'tcx>, - module: Module<'ra>, + module: LocalModule<'ra>, ident: IdentKey, orig_ident_span: Span, ns: Namespace, @@ -1137,7 +1137,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // doesn't need to be mutable. It will fail when there is a cycle of imports, and without // the exclusive access infinite recursion will crash the compiler with stack overflow. let resolution = &*self - .resolution_or_default(module, key, orig_ident_span) + .resolution_or_default(module.to_module(), key, orig_ident_span) .try_borrow_mut_unchecked() .map_err(|_| ControlFlow::Continue(Determined))?; diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index d1a3960afd039..b4f03db96e6ea 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -37,8 +37,8 @@ use crate::errors::{ use crate::ref_mut::CmCell; use crate::{ AmbiguityError, BindingKey, CmResolver, Decl, DeclData, DeclKind, Determinacy, Finalize, - IdentKey, ImportSuggestion, Module, ModuleOrUniformRoot, ParentScope, PathResult, PerNS, Res, - ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string, names_to_string, + IdentKey, ImportSuggestion, LocalModule, ModuleOrUniformRoot, ParentScope, PathResult, PerNS, + Res, ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string, names_to_string, }; /// A potential import declaration in the process of being planted into a module. @@ -471,7 +471,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { decl: Decl<'ra>, warn_ambiguity: bool, ) -> Result<(), Decl<'ra>> { - let module = decl.parent_module.unwrap(); + let module = decl.parent_module.unwrap().expect_local(); let res = decl.res(); self.check_reserved_macro_name(ident.name, orig_ident_span, res); // Even if underscore names cannot be looked up, we still need to add them to modules, @@ -513,7 +513,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // If the resolution becomes a success, define it in the module's glob importers. fn update_local_resolution( &mut self, - module: Module<'ra>, + module: LocalModule<'ra>, key: BindingKey, orig_ident_span: Span, warn_ambiguity: bool, @@ -526,7 +526,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // during which the resolution might end up getting re-defined via a glob cycle. let (binding, t, warn_ambiguity) = { let resolution = &mut *self - .resolution_or_default(module, key, orig_ident_span) + .resolution_or_default(module.to_module(), key, orig_ident_span) .borrow_mut_unchecked(); let old_decl = resolution.determined_decl(); @@ -582,7 +582,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let dummy_decl = self.dummy_decl; let dummy_decl = self.new_import_decl(dummy_decl, import); self.per_ns(|this, ns| { - let module = import.parent_scope.module; let ident = IdentKey::new(target); // This can fail, dummies are inserted only in non-occupied slots. let _ = this.try_plant_decl_into_local_module( @@ -596,7 +595,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if target.name != kw::Underscore { let key = BindingKey::new(ident, ns); this.update_local_resolution( - module, + import.parent_scope.module.expect_local(), key, target.span, false, @@ -734,7 +733,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { pub(crate) fn lint_reexports(&mut self, exported_ambiguities: FxHashSet>) { for module in &self.local_modules { - for (key, resolution) in self.resolutions(*module).borrow().iter() { + for (key, resolution) in self.resolutions(module.to_module()).borrow().iter() { let resolution = resolution.borrow(); let Some(binding) = resolution.best_decl() else { continue }; @@ -1027,7 +1026,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if target.name != kw::Underscore { let key = BindingKey::new(IdentKey::new(target), ns); this.get_mut_unchecked().update_local_resolution( - parent, + parent.expect_local(), key, target.span, false, @@ -1700,7 +1699,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // reporting conflicts, and reporting unresolved imports. fn finalize_resolutions_in( &self, - module: Module<'ra>, + module: LocalModule<'ra>, module_children: &mut LocalDefIdMap>, ambig_module_children: &mut LocalDefIdMap>, ) { @@ -1712,7 +1711,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut children = Vec::new(); let mut ambig_children = Vec::new(); - module.for_each_child(self, |this, ident, orig_ident_span, _, binding| { + module.to_module().for_each_child(self, |this, ident, orig_ident_span, _, binding| { let res = binding.res().expect_non_local(); if res != def::Res::Err { let ident = ident.orig(orig_ident_span); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index a88f06f931389..db71f7ed79d8b 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -40,9 +40,9 @@ use thin_vec::ThinVec; use tracing::{debug, instrument, trace}; use crate::{ - BindingError, BindingKey, Decl, DelegationFnSig, Finalize, IdentKey, LateDecl, Module, - ModuleOrUniformRoot, ParentScope, PathResult, Res, ResolutionError, Resolver, Segment, Stage, - TyCtxt, UseError, Used, errors, path_names_to_string, rustdoc, + BindingError, BindingKey, Decl, DelegationFnSig, Finalize, IdentKey, LateDecl, LocalModule, + Module, ModuleOrUniformRoot, ParentScope, PathResult, Res, ResolutionError, Resolver, Segment, + Stage, TyCtxt, UseError, Used, errors, path_names_to_string, rustdoc, }; mod diagnostics; @@ -196,7 +196,7 @@ pub(crate) enum RibKind<'ra> { /// `Block(None)` must be always processed in the same way as `Block(Some(module))` /// with empty `module`. The module can be `None` only because creation of some definitely /// empty modules is skipped as an optimization. - Block(Option>), + Block(Option>), /// We passed through an impl or trait and are now in one of its /// methods or associated types. Allow references to ty params that impl or trait @@ -217,7 +217,7 @@ pub(crate) enum RibKind<'ra> { ConstantItem(ConstantHasGenerics, Option<(Ident, ConstantItemKind)>), /// We passed through a module item. - Module(Module<'ra>), + Module(LocalModule<'ra>), /// We passed through a `macro_rules!` statement MacroDefinition(DefId), @@ -1473,7 +1473,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // During late resolution we only track the module component of the parent scope, // although it may be useful to track other components as well for diagnostics. let graph_root = resolver.graph_root; - let parent_scope = ParentScope::module(graph_root, resolver.arenas); + let parent_scope = ParentScope::module(graph_root.to_module(), resolver.arenas); let start_rib_kind = RibKind::Module(graph_root); LateResolutionVisitor { r: resolver, @@ -2875,8 +2875,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ItemKind::Mod(..) => { let module = self.r.expect_module(self.r.local_def_id(item.id).to_def_id()); let orig_module = replace(&mut self.parent_scope.module, module); - self.with_rib(ValueNS, RibKind::Module(module), |this| { - this.with_rib(TypeNS, RibKind::Module(module), |this| { + self.with_rib(ValueNS, RibKind::Module(module.expect_local()), |this| { + this.with_rib(TypeNS, RibKind::Module(module.expect_local()), |this| { if mod_inner_docs { this.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); } @@ -5015,7 +5015,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { debug!("(resolving block) found anonymous module, moving down"); self.ribs[ValueNS].push(Rib::new(RibKind::Block(Some(anonymous_module)))); self.ribs[TypeNS].push(Rib::new(RibKind::Block(Some(anonymous_module)))); - self.parent_scope.module = anonymous_module; + self.parent_scope.module = anonymous_module.to_module(); } else { self.ribs[ValueNS].push(Rib::new(RibKind::Block(None))); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index ad8c5e838b486..6f86759d46c5f 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1133,7 +1133,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { for rib in self.ribs[ns].iter().rev() { let item = path[0].ident; if let RibKind::Module(module) | RibKind::Block(Some(module)) = rib.kind - && let Some(did) = find_doc_alias_name(self.r, module, item.name) + && let Some(did) = find_doc_alias_name(self.r, module.to_module(), item.name) { return Some((did, item)); } @@ -2864,10 +2864,16 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } if let RibKind::Block(Some(module)) = rib.kind { - self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt)); + self.r.add_module_candidates( + module.to_module(), + &mut names, + &filter_fn, + Some(ctxt), + ); } else if let RibKind::Module(module) = rib.kind { // Encountered a module item, abandon ribs and look into that module and preludes. - let parent_scope = &ParentScope { module, ..self.parent_scope }; + let parent_scope = + &ParentScope { module: module.to_module(), ..self.parent_scope }; self.r.add_scope_set_candidates( &mut names, ScopeSet::All(ns), @@ -3010,7 +3016,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let mut seen_modules = FxHashSet::default(); let root_did = self.r.graph_root.def_id(); let mut worklist = vec![( - self.r.graph_root, + self.r.graph_root.to_module(), ThinVec::new(), root_did.is_local() || !self.r.tcx.is_doc_hidden(root_did), )]; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 35ef00f945035..444fcb0fe6685 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -686,6 +686,16 @@ struct ModuleData<'ra> { #[rustc_pass_by_value] struct Module<'ra>(Interned<'ra, ModuleData<'ra>>); +/// Same as `Module`, but is guaranteed to be from the current crate. +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[rustc_pass_by_value] +struct LocalModule<'ra>(Interned<'ra, ModuleData<'ra>>); + +/// Same as `Module`, but is guaranteed to be from an external crate. +#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[rustc_pass_by_value] +struct ExternModule<'ra>(Interned<'ra, ModuleData<'ra>>); + // Allows us to use Interned without actually enforcing (via Hash/PartialEq/...) uniqueness of the // contained data. // FIXME: We may wish to actually have at least debug-level assertions that Interned's guarantees @@ -728,6 +738,21 @@ impl<'ra> ModuleData<'ra> { self_decl, } } + + fn opt_def_id(&self) -> Option { + self.kind.opt_def_id() + } + + fn def_id(&self) -> DefId { + self.opt_def_id().expect("`ModuleData::def_id` is called on a block module") + } + + fn res(&self) -> Option { + match self.kind { + ModuleKind::Def(kind, def_id, _) => Some(Res::Def(kind, def_id)), + _ => None, + } + } } impl<'ra> Module<'ra> { @@ -779,21 +804,6 @@ impl<'ra> Module<'ra> { } } - fn res(self) -> Option { - match self.kind { - ModuleKind::Def(kind, def_id, _) => Some(Res::Def(kind, def_id)), - _ => None, - } - } - - 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 { - self.kind.opt_def_id() - } - // `self` resolves to the first module ancestor that `is_normal`. fn is_normal(self) -> bool { matches!(self.kind, ModuleKind::Def(DefKind::Mod, _, _)) @@ -831,6 +841,38 @@ impl<'ra> Module<'ra> { } true } + + #[track_caller] + fn expect_local(self) -> LocalModule<'ra> { + match self.kind { + ModuleKind::Def(_, def_id, _) if !def_id.is_local() => { + panic!("`Module::expect_local` is called on a non-local module: {self:?}") + } + ModuleKind::Def(..) | ModuleKind::Block => LocalModule(self.0), + } + } + + #[track_caller] + fn expect_extern(self) -> ExternModule<'ra> { + match self.kind { + ModuleKind::Def(_, def_id, _) if !def_id.is_local() => ExternModule(self.0), + ModuleKind::Def(..) | ModuleKind::Block => { + panic!("`Module::expect_extern` is called on a local module: {self:?}") + } + } + } +} + +impl<'ra> LocalModule<'ra> { + fn to_module(self) -> Module<'ra> { + Module(self.0) + } +} + +impl<'ra> ExternModule<'ra> { + fn to_module(self) -> Module<'ra> { + Module(self.0) + } } impl<'ra> std::ops::Deref for Module<'ra> { @@ -841,6 +883,22 @@ impl<'ra> std::ops::Deref for Module<'ra> { } } +impl<'ra> std::ops::Deref for LocalModule<'ra> { + type Target = ModuleData<'ra>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl<'ra> std::ops::Deref for ExternModule<'ra> { + type Target = ModuleData<'ra>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + impl<'ra> fmt::Debug for Module<'ra> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.kind { @@ -850,6 +908,12 @@ impl<'ra> fmt::Debug for Module<'ra> { } } +impl<'ra> fmt::Debug for LocalModule<'ra> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.to_module().fmt(f) + } +} + /// Data associated with any name declaration. #[derive(Clone, Debug)] struct DeclData<'ra> { @@ -1197,7 +1261,7 @@ pub struct Resolver<'ra, 'tcx> { /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. expn_that_defined: UnordMap = Default::default(), - graph_root: Module<'ra>, + graph_root: LocalModule<'ra>, /// Assert that we are in speculative resolution mode. assert_speculative: bool, @@ -1256,17 +1320,17 @@ pub struct Resolver<'ra, 'tcx> { /// /// There will be an anonymous module created around `g` with the ID of the /// entry block for `f`. - block_map: NodeMap> = Default::default(), + block_map: NodeMap> = Default::default(), /// A fake module that contains no definition and no prelude. Used so that /// some AST passes can generate identifiers that only resolve to local or /// lang items. - empty_module: Module<'ra>, + empty_module: LocalModule<'ra>, /// All local modules, including blocks. - local_modules: Vec>, + local_modules: Vec>, /// Eagerly populated map of all local non-block modules. - local_module_map: FxIndexMap>, + local_module_map: FxIndexMap>, /// Lazily populated cache of modules loaded from external crates. - extern_module_map: CacheRefCell>>, + extern_module_map: CacheRefCell>>, /// Maps glob imports to the names of items actually imported. glob_map: FxIndexMap>, @@ -1301,8 +1365,8 @@ pub struct Resolver<'ra, 'tcx> { dummy_ext_bang: Arc, dummy_ext_derive: Arc, non_macro_attr: &'ra MacroData, - local_macro_def_scopes: FxHashMap> = default::fx_hash_map(), - ast_transform_scopes: FxHashMap> = default::fx_hash_map(), + local_macro_def_scopes: FxHashMap> = default::fx_hash_map(), + ast_transform_scopes: FxHashMap> = default::fx_hash_map(), unused_macros: FxIndexMap, /// A map from the macro to all its potentially unused arms. unused_macro_rules: FxIndexMap>, @@ -1650,6 +1714,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { crate_span, attr::contains_name(attrs, sym::no_implicit_prelude), ); + let graph_root = graph_root.expect_local(); let local_modules = vec![graph_root]; let local_module_map = FxIndexMap::from_iter([(CRATE_DEF_ID, graph_root)]); let empty_module = arenas.new_module( @@ -1660,6 +1725,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { DUMMY_SP, true, ); + let empty_module = empty_module.expect_local(); let mut node_id_to_def_id = NodeMap::default(); let crate_feed = tcx.create_local_crate_def_id(crate_span); @@ -1742,7 +1808,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .. }; - let root_parent_scope = ParentScope::module(graph_root, resolver.arenas); + let root_parent_scope = ParentScope::module(graph_root.to_module(), resolver.arenas); resolver.invocation_parent_scopes.insert(LocalExpnId::ROOT, root_parent_scope); resolver.feed_visibility(crate_feed, Visibility::Public); @@ -1751,15 +1817,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn new_local_module( &mut self, - parent: Option>, + parent: Option>, kind: ModuleKind, expn_id: ExpnId, span: Span, no_implicit_prelude: bool, - ) -> Module<'ra> { + ) -> LocalModule<'ra> { + let parent = parent.map(|m| m.to_module()); let vis = kind.opt_def_id().map_or(Visibility::Public, |def_id| self.tcx.visibility(def_id)); - let module = self.arenas.new_module(parent, kind, vis, expn_id, span, no_implicit_prelude); + let module = self + .arenas + .new_module(parent, kind, vis, expn_id, span, no_implicit_prelude) + .expect_local(); self.local_modules.push(module); if let Some(def_id) = module.opt_def_id() { self.local_module_map.insert(def_id.expect_local(), module); @@ -1769,15 +1839,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn new_extern_module( &self, - parent: Option>, + parent: Option>, kind: ModuleKind, expn_id: ExpnId, span: Span, no_implicit_prelude: bool, - ) -> Module<'ra> { + ) -> ExternModule<'ra> { + let parent = parent.map(|m| m.to_module()); let vis = kind.opt_def_id().map_or(Visibility::Public, |def_id| self.tcx.visibility(def_id)); - let module = self.arenas.new_module(parent, kind, vis, expn_id, span, no_implicit_prelude); + let module = self + .arenas + .new_module(parent, kind, vis, expn_id, span, no_implicit_prelude) + .expect_extern(); self.extern_module_map.borrow_mut().insert(module.def_id(), module); module } @@ -2063,7 +2137,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { fn resolutions(&self, module: Module<'ra>) -> &'ra Resolutions<'ra> { if module.populate_on_access.get() { module.populate_on_access.set(false); - self.build_reduced_graph_external(module); + self.build_reduced_graph_external(module.expect_extern()); } &module.0.0.lazy_resolutions } @@ -2136,7 +2210,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Do not report the lint if the macro name resolves in stdlib prelude // even without the problematic `macro_use` import. let found_in_stdlib_prelude = self.prelude.is_some_and(|prelude| { - let empty_module = self.empty_module; + let empty_module = self.empty_module.to_module(); let arenas = self.arenas; self.cm() .maybe_resolve_ident_in_module( @@ -2248,7 +2322,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { "resolve_crate_root({:?}): found no mark (ident.span = {:?})", ident, ident.span ); - return self.graph_root; + return self.graph_root.to_module(); } }; let module = self.expect_module( @@ -2503,7 +2577,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { return; } - let module = self.graph_root; + let module = self.graph_root.to_module(); let ident = Ident::with_dummy_span(sym::main); let parent_scope = &ParentScope::module(module, self.arenas); diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 68242fba473d6..2de4e21b1e96a 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -240,8 +240,8 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { ) }); - let parent_scope = - parent_module.map_or(self.empty_module, |def_id| self.expect_module(def_id)); + let parent_scope = parent_module + .map_or(self.empty_module, |def_id| self.expect_module(def_id).expect_local()); self.ast_transform_scopes.insert(expn_id, parent_scope); expn_id diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 73fd7e4b6023c..4e6d886658595 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -3513,7 +3513,13 @@ impl Weak { /// Attempts to upgrade the `Weak` pointer to an [`Rc`], delaying /// dropping of the inner value if successful. /// - /// Returns [`None`] if the inner value has since been dropped. + /// Returns [`None`] in the following cases: + /// + /// 1. The inner value has since been dropped or moved out. + /// + /// 2. This `Weak` does not point to an allocation. + /// + /// 3. The owning reference this `Weak` is associated with is either not fully-constructed or does not allow an upgrade. /// /// # Examples /// diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 645a55843f359..8004dd38d073b 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -3244,7 +3244,13 @@ impl Weak { /// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying /// dropping of the inner value if successful. /// - /// Returns [`None`] if the inner value has since been dropped. + /// Returns [`None`] in the following cases: + /// + /// 1. The inner value has since been dropped or moved out. + /// + /// 2. This `Weak` does not point to an allocation. + /// + /// 3. The owning reference this `Weak` is associated with is either not fully-constructed or does not allow an upgrade. /// /// # Examples /// diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index a5c9eaf9035a0..a56ce1806d528 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -1,4 +1,4 @@ -use crate::num::TryFromIntError; +use crate::num::{IntErrorKind, TryFromIntError}; mod private { /// This trait being unreachable from outside the crate @@ -278,7 +278,7 @@ macro_rules! impl_try_from_lower_bounded { if u >= 0 { Ok(u as Self) } else { - Err(TryFromIntError(())) + Err(TryFromIntError(IntErrorKind::NegOverflow)) } } } @@ -299,7 +299,7 @@ macro_rules! impl_try_from_upper_bounded { #[inline] fn try_from(u: $source) -> Result { if u > (Self::MAX as $source) { - Err(TryFromIntError(())) + Err(TryFromIntError(IntErrorKind::PosOverflow)) } else { Ok(u as Self) } @@ -323,8 +323,10 @@ macro_rules! impl_try_from_both_bounded { fn try_from(u: $source) -> Result { let min = Self::MIN as $source; let max = Self::MAX as $source; - if u < min || u > max { - Err(TryFromIntError(())) + if u < min { + Err(TryFromIntError(IntErrorKind::NegOverflow)) + } else if u > max { + Err(TryFromIntError(IntErrorKind::PosOverflow)) } else { Ok(u as Self) } @@ -335,7 +337,7 @@ macro_rules! impl_try_from_both_bounded { /// Implement `TryFrom` for `bool` macro_rules! impl_try_from_integer_for_bool { - ($($int:ty)+) => {$( + ($signedness:ident $($int:ty)+) => {$( #[stable(feature = "bool_try_from_int", since = "1.95.0")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] impl const TryFrom<$int> for bool { @@ -355,10 +357,23 @@ macro_rules! impl_try_from_integer_for_bool { /// ``` #[inline] fn try_from(i: $int) -> Result { - match i { - 0 => Ok(false), - 1 => Ok(true), - _ => Err(TryFromIntError(())), + sign_dependent_expr!{ + $signedness ? + if signed { + match i { + 0 => Ok(false), + 1 => Ok(true), + ..0 => Err(TryFromIntError(IntErrorKind::NegOverflow)), + 2.. => Err(TryFromIntError(IntErrorKind::PosOverflow)), + } + } + if unsigned { + match i { + 0 => Ok(false), + 1 => Ok(true), + 2.. => Err(TryFromIntError(IntErrorKind::PosOverflow)), + } + } } } } @@ -372,8 +387,8 @@ macro_rules! rev { } // integer -> bool -impl_try_from_integer_for_bool!(u128 u64 u32 u16 u8); -impl_try_from_integer_for_bool!(i128 i64 i32 i16 i8); +impl_try_from_integer_for_bool!(unsigned u128 u64 u32 u16 u8); +impl_try_from_integer_for_bool!(signed i128 i64 i32 i16 i8); // unsigned integer -> unsigned integer impl_try_from_upper_bounded!(u16 => u8); @@ -411,7 +426,7 @@ impl_try_from_lower_bounded!(isize => usize); #[cfg(target_pointer_width = "16")] mod ptr_try_from_impls { - use super::TryFromIntError; + use super::{IntErrorKind, TryFromIntError}; impl_try_from_upper_bounded!(usize => u8); impl_try_from_unbounded!(usize => u16, u32, u64, u128); @@ -433,7 +448,7 @@ mod ptr_try_from_impls { #[cfg(target_pointer_width = "32")] mod ptr_try_from_impls { - use super::TryFromIntError; + use super::{IntErrorKind, TryFromIntError}; impl_try_from_upper_bounded!(usize => u8, u16); impl_try_from_unbounded!(usize => u32, u64, u128); @@ -458,7 +473,7 @@ mod ptr_try_from_impls { #[cfg(target_pointer_width = "64")] mod ptr_try_from_impls { - use super::TryFromIntError; + use super::{IntErrorKind, TryFromIntError}; impl_try_from_upper_bounded!(usize => u8, u16, u32); impl_try_from_unbounded!(usize => u64, u128); @@ -556,7 +571,7 @@ macro_rules! impl_nonzero_int_try_from_int { #[doc = concat!("to [NonZero]\\<[", stringify!($Int), "]>.")] #[inline] fn try_from(value: $Int) -> Result { - Self::new(value).ok_or(TryFromIntError(())) + Self::new(value).ok_or(TryFromIntError(IntErrorKind::Zero)) } } }; diff --git a/library/core/src/mem/alignment.rs b/library/core/src/mem/alignment.rs index 82f693f0a9ccc..a57d8e8535900 100644 --- a/library/core/src/mem/alignment.rs +++ b/library/core/src/mem/alignment.rs @@ -281,7 +281,7 @@ impl const TryFrom for Alignment { #[inline] fn try_from(align: usize) -> Result { - Self::new(align).ok_or(num::TryFromIntError(())) + Self::new(align).ok_or(num::TryFromIntError(num::IntErrorKind::NotAPowerOfTwo)) } } diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs index 8a353dc0fbe99..f01c0f92567ae 100644 --- a/library/core/src/num/error.rs +++ b/library/core/src/num/error.rs @@ -7,7 +7,16 @@ use crate::fmt; /// The error type returned when a checked integral type conversion fails. #[stable(feature = "try_from", since = "1.34.0")] #[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct TryFromIntError(pub(crate) ()); +pub struct TryFromIntError(pub(crate) IntErrorKind); + +impl TryFromIntError { + /// Outputs the detailed cause of converting an integer failing. + #[must_use] + #[unstable(feature = "try_from_int_error_kind", issue = "153978")] + pub const fn kind(&self) -> &IntErrorKind { + &self.0 + } +} #[stable(feature = "try_from", since = "1.34.0")] impl fmt::Display for TryFromIntError { @@ -66,7 +75,8 @@ pub struct ParseIntError { pub(super) kind: IntErrorKind, } -/// Enum to store the various types of errors that can cause parsing an integer to fail. +/// Enum to store the various types of errors that can cause parsing or converting an +/// integer to fail. /// /// # Example /// @@ -103,10 +113,19 @@ pub enum IntErrorKind { NegOverflow, /// Value was Zero /// - /// This variant will be emitted when the parsing string has a value of zero, which - /// would be illegal for non-zero types. + /// This variant will be emitted when the parsing string or the converting integer + /// has a value of zero, which would be illegal for non-zero types. #[stable(feature = "int_error_matching", since = "1.55.0")] Zero, + /// Value is not a power of two. + /// + /// This variant will be emitted when converting an integer that is not a power of + /// two. This is required in some cases such as constructing an [`Alignment`]. + /// + /// [`Alignment`]: core::ptr::Alignment "ptr::Alignment" + #[unstable(feature = "try_from_int_error_kind", issue = "153978")] + // Also, #[unstable(feature = "ptr_alignment_type", issue = "102070")] + NotAPowerOfTwo, } impl ParseIntError { @@ -128,6 +147,7 @@ impl fmt::Display for ParseIntError { IntErrorKind::PosOverflow => "number too large to fit in target type", IntErrorKind::NegOverflow => "number too small to fit in target type", IntErrorKind::Zero => "number would be zero for non-zero type", + IntErrorKind::NotAPowerOfTwo => "number is not a power of two", } .fmt(f) } diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 019a2dfaa4476..2c561b5b0529e 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -117,6 +117,7 @@ #![feature(trusted_random_access)] #![feature(try_blocks)] #![feature(try_find)] +#![feature(try_from_int_error_kind)] #![feature(try_trait_v2)] #![feature(type_info)] #![feature(uint_carryless_mul)] diff --git a/library/coretests/tests/nonzero.rs b/library/coretests/tests/nonzero.rs index 861e9e05081fc..55d479efb4b40 100644 --- a/library/coretests/tests/nonzero.rs +++ b/library/coretests/tests/nonzero.rs @@ -282,11 +282,11 @@ fn test_nonzero_from_int_on_success() { #[test] fn test_nonzero_from_int_on_err() { - assert!(NonZero::::try_from(0).is_err()); - assert!(NonZero::::try_from(0).is_err()); + assert_eq!(NonZero::::try_from(0).unwrap_err().kind(), &IntErrorKind::Zero); + assert_eq!(NonZero::::try_from(0).unwrap_err().kind(), &IntErrorKind::Zero); - assert!(NonZero::::try_from(0).is_err()); - assert!(NonZero::::try_from(0).is_err()); + assert_eq!(NonZero::::try_from(0).unwrap_err().kind(), &IntErrorKind::Zero); + assert_eq!(NonZero::::try_from(0).unwrap_err().kind(), &IntErrorKind::Zero); } #[test] diff --git a/library/coretests/tests/num/mod.rs b/library/coretests/tests/num/mod.rs index e0214c6ae6868..a82ac6fcd45f0 100644 --- a/library/coretests/tests/num/mod.rs +++ b/library/coretests/tests/num/mod.rs @@ -374,6 +374,43 @@ fn test_f32f64() { assert!(nan.is_nan()); } +/// Conversions where $source can be represented as bool. +macro_rules! test_impl_try_from_integer_to_bool { + ($fn_name:ident, $source:ty) => { + #[test] + fn $fn_name() { + let max: $source = <$source>::MAX; + let min: $source = <$source>::MIN; + let zero: $source = 0; + let one: $source = 1; + let two: $source = 2; + assert_eq!(bool::try_from(max).unwrap_err().kind(), &IntErrorKind::PosOverflow); + if min != 0 { + assert_eq!(bool::try_from(min).unwrap_err().kind(), &IntErrorKind::NegOverflow); + assert_eq!( + bool::try_from(zero - 1).unwrap_err().kind(), + &IntErrorKind::NegOverflow + ); + } + assert_eq!(bool::try_from(zero).unwrap(), false); + assert_eq!(bool::try_from(one).unwrap(), true); + assert_eq!(bool::try_from(two).unwrap_err().kind(), &IntErrorKind::PosOverflow); + } + }; +} + +test_impl_try_from_integer_to_bool! { test_try_u8bool, u8 } +test_impl_try_from_integer_to_bool! { test_try_u16bool, u16 } +test_impl_try_from_integer_to_bool! { test_try_u32bool, u32 } +test_impl_try_from_integer_to_bool! { test_try_u64bool, u64 } +test_impl_try_from_integer_to_bool! { test_try_u128bool, u128 } + +test_impl_try_from_integer_to_bool! { test_try_i8bool, i8 } +test_impl_try_from_integer_to_bool! { test_try_i16bool, i16 } +test_impl_try_from_integer_to_bool! { test_try_i32bool, i32 } +test_impl_try_from_integer_to_bool! { test_try_i64bool, i64 } +test_impl_try_from_integer_to_bool! { test_try_i128bool, i128 } + /// Conversions where the full width of $source can be represented as $target macro_rules! test_impl_try_from_always_ok { ($fn_name:ident, $source:ty, $target: ty) => { @@ -497,9 +534,15 @@ macro_rules! test_impl_try_from_signed_to_unsigned_upper_ok { let zero: $source = 0; let neg_one: $source = -1; assert_eq!(<$target as TryFrom<$source>>::try_from(max).unwrap(), max as $target); - assert!(<$target as TryFrom<$source>>::try_from(min).is_err()); + assert_eq!( + <$target as TryFrom<$source>>::try_from(min).unwrap_err().kind(), + &IntErrorKind::NegOverflow + ); assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(), zero as $target); - assert!(<$target as TryFrom<$source>>::try_from(neg_one).is_err()); + assert_eq!( + <$target as TryFrom<$source>>::try_from(neg_one).unwrap_err().kind(), + &IntErrorKind::NegOverflow + ); } }; } @@ -560,7 +603,10 @@ macro_rules! test_impl_try_from_unsigned_to_signed_upper_err { let max = <$source>::MAX; let min = <$source>::MIN; let zero: $source = 0; - assert!(<$target as TryFrom<$source>>::try_from(max).is_err()); + assert_eq!( + <$target as TryFrom<$source>>::try_from(max).unwrap_err().kind(), + &IntErrorKind::PosOverflow + ); assert_eq!(<$target as TryFrom<$source>>::try_from(min).unwrap(), min as $target); assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(), zero as $target); } @@ -623,9 +669,15 @@ macro_rules! test_impl_try_from_same_sign_err { let zero: $source = 0; let t_max = <$target>::MAX; let t_min = <$target>::MIN; - assert!(<$target as TryFrom<$source>>::try_from(max).is_err()); + assert_eq!( + <$target as TryFrom<$source>>::try_from(max).unwrap_err().kind(), + &IntErrorKind::PosOverflow + ); if min != 0 { - assert!(<$target as TryFrom<$source>>::try_from(min).is_err()); + assert_eq!( + <$target as TryFrom<$source>>::try_from(min).unwrap_err().kind(), + &IntErrorKind::NegOverflow + ); } assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(), zero as $target); assert_eq!( @@ -712,8 +764,14 @@ macro_rules! test_impl_try_from_signed_to_unsigned_err { let zero: $source = 0; let t_max = <$target>::MAX; let t_min = <$target>::MIN; - assert!(<$target as TryFrom<$source>>::try_from(max).is_err()); - assert!(<$target as TryFrom<$source>>::try_from(min).is_err()); + assert_eq!( + <$target as TryFrom<$source>>::try_from(max).unwrap_err().kind(), + &IntErrorKind::PosOverflow + ); + assert_eq!( + <$target as TryFrom<$source>>::try_from(min).unwrap_err().kind(), + &IntErrorKind::NegOverflow + ); assert_eq!(<$target as TryFrom<$source>>::try_from(zero).unwrap(), zero as $target); assert_eq!( <$target as TryFrom<$source>>::try_from(t_max as $source).unwrap(), diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 2b347e5e8c286..faac8d9e51fd2 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -347,6 +347,7 @@ #![feature(ip)] #![feature(iter_advance_by)] #![feature(iter_next_chunk)] +#![feature(maybe_dangling)] #![feature(maybe_uninit_array_assume_init)] #![feature(maybe_uninit_fill)] #![feature(panic_can_unwind)] diff --git a/library/std/src/thread/lifecycle.rs b/library/std/src/thread/lifecycle.rs index 0bb1f347ffaad..af239bee55189 100644 --- a/library/std/src/thread/lifecycle.rs +++ b/library/std/src/thread/lifecycle.rs @@ -7,7 +7,7 @@ use super::thread::Thread; use super::{Result, spawnhook}; use crate::cell::UnsafeCell; use crate::marker::PhantomData; -use crate::mem::{ManuallyDrop, MaybeUninit}; +use crate::mem::MaybeDangling; use crate::sync::Arc; use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; use crate::sys::{AsInner, IntoInner, thread as imp}; @@ -57,29 +57,8 @@ where Arc::new(Packet { scope: scope_data, result: UnsafeCell::new(None), _marker: PhantomData }); let their_packet = my_packet.clone(); - // Pass `f` in `MaybeUninit` because actually that closure might *run longer than the lifetime of `F`*. + // Pass `f` in `MaybeDangling` because actually that closure might *run longer than the lifetime of `F`*. // See for more details. - // To prevent leaks we use a wrapper that drops its contents. - #[repr(transparent)] - struct MaybeDangling(MaybeUninit); - impl MaybeDangling { - fn new(x: T) -> Self { - MaybeDangling(MaybeUninit::new(x)) - } - fn into_inner(self) -> T { - // Make sure we don't drop. - let this = ManuallyDrop::new(self); - // SAFETY: we are always initialized. - unsafe { this.0.assume_init_read() } - } - } - impl Drop for MaybeDangling { - fn drop(&mut self) { - // SAFETY: we are always initialized. - unsafe { self.0.assume_init_drop() }; - } - } - let f = MaybeDangling::new(f); // The entrypoint of the Rust thread, after platform-specific thread diff --git a/tests/ui/attributes/attr-order-deprecated.rs b/tests/ui/attributes/attr-order-deprecated.rs new file mode 100644 index 0000000000000..606e714819b50 --- /dev/null +++ b/tests/ui/attributes/attr-order-deprecated.rs @@ -0,0 +1,11 @@ +#[deprecated = "AAA"] +//~^ NOTE also specified here +#[deprecated = "BBB"] +//~^ ERROR multiple `deprecated` attributes +fn deprecated() { } + +fn main() { + deprecated(); + //~^ WARN use of deprecated function `deprecated`: AAA [deprecated] + //~| NOTE `#[warn(deprecated)]` on by default +} diff --git a/tests/ui/attributes/attr-order-deprecated.stderr b/tests/ui/attributes/attr-order-deprecated.stderr new file mode 100644 index 0000000000000..41e26bec761ee --- /dev/null +++ b/tests/ui/attributes/attr-order-deprecated.stderr @@ -0,0 +1,22 @@ +error: multiple `deprecated` attributes + --> $DIR/attr-order-deprecated.rs:3:1 + | +LL | #[deprecated = "BBB"] + | ^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/attr-order-deprecated.rs:1:1 + | +LL | #[deprecated = "AAA"] + | ^^^^^^^^^^^^^^^^^^^^^ + +warning: use of deprecated function `deprecated`: AAA + --> $DIR/attr-order-deprecated.rs:8:5 + | +LL | deprecated(); + | ^^^^^^^^^^ + | + = note: `#[warn(deprecated)]` on by default + +error: aborting due to 1 previous error; 1 warning emitted + diff --git a/tests/ui/attributes/attr-order-must-use.rs b/tests/ui/attributes/attr-order-must-use.rs new file mode 100644 index 0000000000000..36ffe9d5ed708 --- /dev/null +++ b/tests/ui/attributes/attr-order-must-use.rs @@ -0,0 +1,19 @@ +#![deny(unused)] +//~^ NOTE lint level is defined here + +#[must_use = "AAA"] +//~^ NOTE also specified here +#[must_use = "BBB"] +//~^ ERROR unused attribute +//~| WARN previously accepted +//~| NOTE `#[deny(unused_attributes)]` implied by `#[deny(unused)]` +fn must_use() -> usize { + 0 +} + +fn main() { + must_use(); + //~^ ERROR unused return value of `must_use` that must be used + //~| NOTE AAA + //~| NOTE `#[deny(unused_must_use)]` implied by `#[deny(unused)]` +} diff --git a/tests/ui/attributes/attr-order-must-use.stderr b/tests/ui/attributes/attr-order-must-use.stderr new file mode 100644 index 0000000000000..18b5811623017 --- /dev/null +++ b/tests/ui/attributes/attr-order-must-use.stderr @@ -0,0 +1,34 @@ +error: unused attribute + --> $DIR/attr-order-must-use.rs:6:1 + | +LL | #[must_use = "BBB"] + | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/attr-order-must-use.rs:4:1 + | +LL | #[must_use = "AAA"] + | ^^^^^^^^^^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +note: the lint level is defined here + --> $DIR/attr-order-must-use.rs:1:9 + | +LL | #![deny(unused)] + | ^^^^^^ + = note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]` + +error: unused return value of `must_use` that must be used + --> $DIR/attr-order-must-use.rs:15:5 + | +LL | must_use(); + | ^^^^^^^^^^ + | + = note: AAA + = note: `#[deny(unused_must_use)]` implied by `#[deny(unused)]` +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = must_use(); + | +++++++ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/attributes/malformed-no-std.stderr b/tests/ui/attributes/malformed-no-std.stderr index b2187ae0badc9..d46eaf7368e84 100644 --- a/tests/ui/attributes/malformed-no-std.stderr +++ b/tests/ui/attributes/malformed-no-std.stderr @@ -131,10 +131,10 @@ LL | #![no_std(foo = "bar")] | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/malformed-no-std.rs:5:1 + --> $DIR/malformed-no-std.rs:3:1 | -LL | #![no_std("bar")] - | ^^^^^^^^^^^^^^^^^ +LL | #![no_std = "foo"] + | ^^^^^^^^^^^^^^^^^^ warning: unused attribute --> $DIR/malformed-no-std.rs:13:1 @@ -155,10 +155,10 @@ LL | #![no_core(foo = "bar")] | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | note: attribute also specified here - --> $DIR/malformed-no-std.rs:13:1 + --> $DIR/malformed-no-std.rs:11:1 | -LL | #![no_core("bar")] - | ^^^^^^^^^^^^^^^^^^ +LL | #![no_core = "foo"] + | ^^^^^^^^^^^^^^^^^^^ error: aborting due to 8 previous errors; 4 warnings emitted