diff --git a/src/doc/unstable-book/src/library-features/default-free-fn.md b/src/doc/unstable-book/src/library-features/default-free-fn.md new file mode 100644 index 0000000000000..5dff73a94dd87 --- /dev/null +++ b/src/doc/unstable-book/src/library-features/default-free-fn.md @@ -0,0 +1,45 @@ +# `default_free_fn` + +The tracking issue for this feature is: [#73014] + +[#73014]: https://github.com/rust-lang/rust/issues/73014 + +------------------------ + +Adds a free `default()` function to the `std::default` module. This function +just forwards to [`Default::default()`], but may remove repetition of the word +"default" from the call site. + +Here is an example: + +```rust +#![feature(default_free_fn)] +use std::default::default; + +#[derive(Default)] +struct AppConfig { + foo: FooConfig, + bar: BarConfig, +} + +#[derive(Default)] +struct FooConfig { + foo: i32, +} + +#[derive(Default)] +struct BarConfig { + bar: f32, + baz: u8, +} + +fn main() { + let options = AppConfig { + foo: default(), + bar: BarConfig { + bar: 10.1, + ..default() + }, + }; +} +``` diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 06402a05d2687..9a8d65cd4e06b 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -115,6 +115,50 @@ pub trait Default: Sized { fn default() -> Self; } +/// Return the default value of a type according to the `Default` trait. +/// +/// The type to return is inferred from context; this is equivalent to +/// `Default::default()` but shorter to type. +/// +/// For example: +/// ``` +/// #![feature(default_free_fn)] +/// +/// use std::default::default; +/// +/// #[derive(Default)] +/// struct AppConfig { +/// foo: FooConfig, +/// bar: BarConfig, +/// } +/// +/// #[derive(Default)] +/// struct FooConfig { +/// foo: i32, +/// } +/// +/// #[derive(Default)] +/// struct BarConfig { +/// bar: f32, +/// baz: u8, +/// } +/// +/// fn main() { +/// let options = AppConfig { +/// foo: default(), +/// bar: BarConfig { +/// bar: 10.1, +/// ..default() +/// }, +/// }; +/// } +/// ``` +#[unstable(feature = "default_free_fn", issue = "73014")] +#[inline] +pub fn default() -> T { + Default::default() +} + /// Derive macro generating an impl of the trait `Default`. #[rustc_builtin_macro] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] diff --git a/src/librustc_error_codes/error_codes/E0646.md b/src/librustc_error_codes/error_codes/E0646.md index e01dbae8b9060..1e9ec7d4380ad 100644 --- a/src/librustc_error_codes/error_codes/E0646.md +++ b/src/librustc_error_codes/error_codes/E0646.md @@ -1,4 +1,5 @@ It is not possible to define `main` with a where clause. + Erroneous code example: ```compile_fail,E0646 diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 9964c9c94c951..64ccd46a744f5 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -693,16 +693,25 @@ impl EncodeContext<'tcx> { vis: &hir::Visibility<'_>, ) { let tcx = self.tcx; - let def_id = tcx.hir().local_def_id(id).to_def_id(); + let def_id = tcx.hir().local_def_id(id); debug!("EncodeContext::encode_info_for_mod({:?})", def_id); let data = ModData { reexports: match tcx.module_exports(def_id) { - Some(exports) => self.lazy(exports), + Some(exports) => { + let hir_map = self.tcx.hir(); + self.lazy( + exports + .iter() + .map(|export| export.map_id(|id| hir_map.as_local_hir_id(id))), + ) + } _ => Lazy::empty(), }, }; + let def_id = def_id.to_def_id(); + record!(self.tables.kind[def_id] <- EntryKind::Mod(self.lazy(data))); record!(self.tables.visibility[def_id] <- ty::Visibility::from_hir(vis, id, self.tcx)); record!(self.tables.span[def_id] <- self.tcx.def_span(def_id)); diff --git a/src/librustc_middle/hir/exports.rs b/src/librustc_middle/hir/exports.rs index 83baf6cc43345..af48c9e94ff82 100644 --- a/src/librustc_middle/hir/exports.rs +++ b/src/librustc_middle/hir/exports.rs @@ -1,7 +1,8 @@ use crate::ty; +use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::Res; -use rustc_hir::def_id::DefIdMap; +use rustc_hir::def_id::LocalDefId; use rustc_macros::HashStable; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -10,7 +11,7 @@ use std::fmt::Debug; /// This is the replacement export map. It maps a module to all of the exports /// within. -pub type ExportMap = DefIdMap>>; +pub type ExportMap = FxHashMap>>; #[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct Export { diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs index 5a3ab205fc238..16ed9aff8f2a6 100644 --- a/src/librustc_middle/query/mod.rs +++ b/src/librustc_middle/query/mod.rs @@ -865,8 +865,8 @@ rustc_queries! { } Other { - query module_exports(def_id: DefId) -> Option<&'tcx [Export]> { - desc { |tcx| "looking up items exported by `{}`", tcx.def_path_str(def_id) } + query module_exports(def_id: LocalDefId) -> Option<&'tcx [Export]> { + desc { |tcx| "looking up items exported by `{}`", tcx.def_path_str(def_id.to_def_id()) } eval_always } } diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index 089a1613e7d3b..d5be3508d2d80 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -2,7 +2,7 @@ use crate::arena::Arena; use crate::dep_graph::{self, DepConstructor, DepGraph}; -use crate::hir::exports::Export; +use crate::hir::exports::ExportMap; use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintSource}; @@ -919,7 +919,7 @@ pub struct GlobalCtxt<'tcx> { trait_map: FxHashMap>>, /// Export map produced by name resolution. - export_map: FxHashMap>>, + export_map: ExportMap, pub(crate) untracked_crate: &'tcx hir::Crate<'tcx>, pub(crate) definitions: &'tcx Definitions, diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 00c00a63b6b5d..ffbe3a40297c1 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -124,7 +124,7 @@ pub struct ResolverOutputs { pub trait_map: FxHashMap>>, pub maybe_unused_trait_imports: FxHashSet, pub maybe_unused_extern_crates: Vec<(LocalDefId, Span)>, - pub export_map: ExportMap, + pub export_map: ExportMap, pub glob_map: FxHashMap>, /// Extern prelude entries. The value is `true` if the entry was introduced /// via `extern crate` item and not `--extern` option or compiler built-in. diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 9ee3d989bf3f1..2ae063660e38d 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -95,24 +95,30 @@ impl<'a> Resolver<'a> { } crate fn get_module(&mut self, def_id: DefId) -> Module<'a> { + // If this is a local module, it will be in `module_map`, no need to recalculate it. if let Some(def_id) = def_id.as_local() { return self.module_map[&def_id]; } + // Cache module resolution if let Some(&module) = self.extern_module_map.get(&def_id) { return module; } let (name, parent) = if def_id.index == CRATE_DEF_INDEX { + // This is the crate root (self.cstore().crate_name_untracked(def_id.krate), None) } else { let def_key = self.cstore().def_key(def_id); ( + // This unwrap is safe: crates must always have a name def_key.disambiguated_data.data.get_opt_name().unwrap(), + // This unwrap is safe since we know this isn't the root Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id })), ) }; + // Allocate and return a new module with the information we found let kind = ModuleKind::Def(DefKind::Mod, def_id, name); let module = self.arenas.alloc_module(ModuleData::new( parent, diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs index a1e05d21b58d5..74a8b7e2f556d 100644 --- a/src/librustc_resolve/imports.rs +++ b/src/librustc_resolve/imports.rs @@ -1393,8 +1393,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let is_good_import = binding.is_import() && !binding.is_ambiguity() && !ident.span.from_expansion(); if is_good_import || binding.is_macro_def() { - let res = binding.res(); - if res != Res::Err { + let res = binding.res().map_id(|id| this.definitions.local_def_id(id)); + if res != def::Res::Err { reexports.push(Export { ident, res, span: binding.span, vis: binding.vis }); } } @@ -1467,7 +1467,9 @@ impl<'a, 'b> ImportResolver<'a, 'b> { if !reexports.is_empty() { if let Some(def_id) = module.def_id() { - self.r.export_map.insert(def_id, reexports); + // Call to `expect_local` should be fine because current + // code is only called for local modules. + self.r.export_map.insert(def_id.expect_local(), reexports); } } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 00a5d08d6a955..6bd73877fab75 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -878,7 +878,7 @@ pub struct Resolver<'a> { /// `CrateNum` resolutions of `extern crate` items. extern_crate_map: FxHashMap, - export_map: ExportMap, + export_map: ExportMap, trait_map: TraitMap, /// A map from nodes to anonymous modules. @@ -1281,18 +1281,7 @@ impl<'a> Resolver<'a> { pub fn into_outputs(self) -> ResolverOutputs { let definitions = self.definitions; let extern_crate_map = self.extern_crate_map; - let export_map = self - .export_map - .into_iter() - .map(|(k, v)| { - ( - k, - v.into_iter() - .map(|e| e.map_id(|id| definitions.node_id_to_hir_id(id))) - .collect(), - ) - }) - .collect(); + let export_map = self.export_map; let trait_map = self .trait_map .into_iter() @@ -1330,18 +1319,7 @@ impl<'a> Resolver<'a> { definitions: self.definitions.clone(), cstore: Box::new(self.cstore().clone()), extern_crate_map: self.extern_crate_map.clone(), - export_map: self - .export_map - .iter() - .map(|(&k, v)| { - ( - k, - v.iter() - .map(|e| e.map_id(|id| self.definitions.node_id_to_hir_id(id))) - .collect(), - ) - }) - .collect(), + export_map: self.export_map.clone(), trait_map: self .trait_map .iter() diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 381238165274d..5c76c840b1ddd 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -85,9 +85,7 @@ pub struct Item { impl fmt::Debug for Item { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let fake = MAX_DEF_ID.with(|m| { - m.borrow().get(&self.def_id.krate).map(|id| self.def_id >= *id).unwrap_or(false) - }); + let fake = self.is_fake(); let def_id: &dyn fmt::Debug = if fake { &"**FAKE**" } else { &self.def_id }; fmt.debug_struct("Item") @@ -238,6 +236,13 @@ impl Item { _ => false, } } + + /// See comments on next_def_id + pub fn is_fake(&self) -> bool { + MAX_DEF_ID.with(|m| { + m.borrow().get(&self.def_id.krate).map(|id| self.def_id >= *id).unwrap_or(false) + }) + } } #[derive(Clone, Debug)] diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr index 329543114a610..b687f0b0af0ad 100644 --- a/src/test/ui/resolve/issue-2356.stderr +++ b/src/test/ui/resolve/issue-2356.stderr @@ -14,7 +14,16 @@ error[E0425]: cannot find function `default` in this scope --> $DIR/issue-2356.rs:31:5 | LL | default(); - | ^^^^^^^ help: try: `Self::default` + | ^^^^^^^ + | +help: try + | +LL | Self::default(); + | ^^^^^^^^^^^^^ +help: consider importing this function + | +LL | use std::default::default; + | error[E0425]: cannot find value `whiskers` in this scope --> $DIR/issue-2356.rs:39:5