summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs6
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs56
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs7
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs136
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs29
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs26
-rw-r--r--compiler/rustc_mir/src/transform/const_prop.rs10
-rw-r--r--compiler/rustc_mir/src/transform/mod.rs1
-rw-r--r--compiler/rustc_parse/src/lib.rs42
-rw-r--r--compiler/rustc_target/src/spec/windows_gnu_base.rs7
-rw-r--r--library/alloc/benches/vec.rs2
-rw-r--r--library/core/tests/num/mod.rs14
-rw-r--r--library/std/src/collections/hash/map.rs107
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/mod.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/qualify_min_const_fn.rs (renamed from compiler/rustc_mir/src/transform/qualify_min_const_fn.rs)130
18 files changed, 367 insertions, 210 deletions
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index faeb727..87d539f 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -1333,9 +1333,6 @@ fn add_late_link_args(
1333 crate_type: CrateType, 1333 crate_type: CrateType,
1334 codegen_results: &CodegenResults, 1334 codegen_results: &CodegenResults,
1335) { 1335) {
1336 if let Some(args) = sess.target.target.options.late_link_args.get(&flavor) {
1337 cmd.args(args);
1338 }
1339 let any_dynamic_crate = crate_type == CrateType::Dylib 1336 let any_dynamic_crate = crate_type == CrateType::Dylib
1340 || codegen_results.crate_info.dependency_formats.iter().any(|(ty, list)| { 1337 || codegen_results.crate_info.dependency_formats.iter().any(|(ty, list)| {
1341 *ty == crate_type && list.iter().any(|&linkage| linkage == Linkage::Dynamic) 1338 *ty == crate_type && list.iter().any(|&linkage| linkage == Linkage::Dynamic)
@@ -1349,6 +1346,9 @@ fn add_late_link_args(
1349 cmd.args(args); 1346 cmd.args(args);
1350 } 1347 }
1351 } 1348 }
1349 if let Some(args) = sess.target.target.options.late_link_args.get(&flavor) {
1350 cmd.args(args);
1351 }
1352} 1352}
1353 1353
1354/// Add arbitrary "post-link" args defined by the target spec. 1354/// Add arbitrary "post-link" args defined by the target spec.
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 72d54a2..c31e941 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -707,7 +707,11 @@ impl CrateRoot<'_> {
707 707
708impl<'a, 'tcx> CrateMetadataRef<'a> { 708impl<'a, 'tcx> CrateMetadataRef<'a> {
709 fn is_proc_macro(&self, id: DefIndex) -> bool { 709 fn is_proc_macro(&self, id: DefIndex) -> bool {
710 self.root.proc_macro_data.and_then(|data| data.decode(self).find(|x| *x == id)).is_some() 710 self.root
711 .proc_macro_data
712 .as_ref()
713 .and_then(|data| data.macros.decode(self).find(|x| *x == id))
714 .is_some()
711 } 715 }
712 716
713 fn maybe_kind(&self, item_id: DefIndex) -> Option<EntryKind> { 717 fn maybe_kind(&self, item_id: DefIndex) -> Option<EntryKind> {
@@ -729,7 +733,15 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
729 fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro { 733 fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro {
730 // DefIndex's in root.proc_macro_data have a one-to-one correspondence 734 // DefIndex's in root.proc_macro_data have a one-to-one correspondence
731 // with items in 'raw_proc_macros'. 735 // with items in 'raw_proc_macros'.
732 let pos = self.root.proc_macro_data.unwrap().decode(self).position(|i| i == id).unwrap(); 736 let pos = self
737 .root
738 .proc_macro_data
739 .as_ref()
740 .unwrap()
741 .macros
742 .decode(self)
743 .position(|i| i == id)
744 .unwrap();
733 &self.raw_proc_macros.unwrap()[pos] 745 &self.raw_proc_macros.unwrap()[pos]
734 } 746 }
735 747
@@ -766,7 +778,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
766 } 778 }
767 779
768 fn get_span(&self, index: DefIndex, sess: &Session) -> Span { 780 fn get_span(&self, index: DefIndex, sess: &Session) -> Span {
769 self.root.tables.span.get(self, index).unwrap().decode((self, sess)) 781 self.root
782 .tables
783 .span
784 .get(self, index)
785 .unwrap_or_else(|| panic!("Missing span for {:?}", index))
786 .decode((self, sess))
770 } 787 }
771 788
772 fn load_proc_macro(&self, id: DefIndex, sess: &Session) -> SyntaxExtension { 789 fn load_proc_macro(&self, id: DefIndex, sess: &Session) -> SyntaxExtension {
@@ -942,7 +959,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
942 959
943 fn get_stability(&self, id: DefIndex) -> Option<attr::Stability> { 960 fn get_stability(&self, id: DefIndex) -> Option<attr::Stability> {
944 match self.is_proc_macro(id) { 961 match self.is_proc_macro(id) {
945 true => self.root.proc_macro_stability, 962 true => self.root.proc_macro_data.as_ref().unwrap().stability,
946 false => self.root.tables.stability.get(self, id).map(|stab| stab.decode(self)), 963 false => self.root.tables.stability.get(self, id).map(|stab| stab.decode(self)),
947 } 964 }
948 } 965 }
@@ -1035,24 +1052,20 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
1035 where 1052 where
1036 F: FnMut(Export<hir::HirId>), 1053 F: FnMut(Export<hir::HirId>),
1037 { 1054 {
1038 if let Some(proc_macros_ids) = self.root.proc_macro_data.map(|d| d.decode(self)) { 1055 if let Some(data) = &self.root.proc_macro_data {
1039 /* If we are loading as a proc macro, we want to return the view of this crate 1056 /* If we are loading as a proc macro, we want to return the view of this crate
1040 * as a proc macro crate. 1057 * as a proc macro crate.
1041 */ 1058 */
1042 if id == CRATE_DEF_INDEX { 1059 if id == CRATE_DEF_INDEX {
1043 for def_index in proc_macros_ids { 1060 let macros = data.macros.decode(self);
1061 for def_index in macros {
1044 let raw_macro = self.raw_proc_macro(def_index); 1062 let raw_macro = self.raw_proc_macro(def_index);
1045 let res = Res::Def( 1063 let res = Res::Def(
1046 DefKind::Macro(macro_kind(raw_macro)), 1064 DefKind::Macro(macro_kind(raw_macro)),
1047 self.local_def_id(def_index), 1065 self.local_def_id(def_index),
1048 ); 1066 );
1049 let ident = self.item_ident(def_index, sess); 1067 let ident = self.item_ident(def_index, sess);
1050 callback(Export { 1068 callback(Export { ident, res, vis: ty::Visibility::Public, span: ident.span });
1051 ident,
1052 res,
1053 vis: ty::Visibility::Public,
1054 span: self.get_span(def_index, sess),
1055 });
1056 } 1069 }
1057 } 1070 }
1058 return; 1071 return;
@@ -1559,12 +1572,19 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
1559 1572
1560 fn all_def_path_hashes_and_def_ids(&self) -> Vec<(DefPathHash, DefId)> { 1573 fn all_def_path_hashes_and_def_ids(&self) -> Vec<(DefPathHash, DefId)> {
1561 let mut def_path_hashes = self.def_path_hash_cache.lock(); 1574 let mut def_path_hashes = self.def_path_hash_cache.lock();
1562 (0..self.num_def_ids()) 1575 let mut def_index_to_data = |index| {
1563 .map(|index| { 1576 (self.def_path_hash_unlocked(index, &mut def_path_hashes), self.local_def_id(index))
1564 let index = DefIndex::from_usize(index); 1577 };
1565 (self.def_path_hash_unlocked(index, &mut def_path_hashes), self.local_def_id(index)) 1578 if let Some(data) = &self.root.proc_macro_data {
1566 }) 1579 std::iter::once(CRATE_DEF_INDEX)
1567 .collect() 1580 .chain(data.macros.decode(self))
1581 .map(def_index_to_data)
1582 .collect()
1583 } else {
1584 (0..self.num_def_ids())
1585 .map(|index| def_index_to_data(DefIndex::from_usize(index)))
1586 .collect()
1587 }
1568 } 1588 }
1569 1589
1570 /// Get the `DepNodeIndex` corresponding this crate. The result of this 1590 /// Get the `DepNodeIndex` corresponding this crate. The result of this
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index d4f577a..4102cf8 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -179,8 +179,11 @@ provide! { <'tcx> tcx, def_id, other, cdata,
179 }) 179 })
180 } 180 }
181 proc_macro_decls_static => { 181 proc_macro_decls_static => {
182 cdata.root.proc_macro_decls_static.map(|index| { 182 cdata.root.proc_macro_data.as_ref().map(|data| {
183 DefId { krate: def_id.krate, index } 183 DefId {
184 krate: def_id.krate,
185 index: data.proc_macro_decls_static,
186 }
184 }) 187 })
185 } 188 }
186 crate_disambiguator => { cdata.root.disambiguator } 189 crate_disambiguator => { cdata.root.disambiguator }
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 556cf41..c756715 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -68,6 +68,17 @@ pub(super) struct EncodeContext<'a, 'tcx> {
68 hygiene_ctxt: &'a HygieneEncodeContext, 68 hygiene_ctxt: &'a HygieneEncodeContext,
69} 69}
70 70
71/// If the current crate is a proc-macro, returns early with `Lazy:empty()`.
72/// This is useful for skipping the encoding of things that aren't needed
73/// for proc-macro crates.
74macro_rules! empty_proc_macro {
75 ($self:ident) => {
76 if $self.is_proc_macro {
77 return Lazy::empty();
78 }
79 };
80}
81
71macro_rules! encoder_methods { 82macro_rules! encoder_methods {
72 ($($name:ident($ty:ty);)*) => { 83 ($($name:ident($ty:ty);)*) => {
73 $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> { 84 $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> {
@@ -138,6 +149,15 @@ where
138 } 149 }
139} 150}
140 151
152impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for CrateNum {
153 fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
154 if *self != LOCAL_CRATE && s.is_proc_macro {
155 panic!("Attempted to encode non-local CrateNum {:?} for proc-macro crate", self);
156 }
157 s.emit_u32(self.as_u32())
158 }
159}
160
141impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for DefIndex { 161impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for DefIndex {
142 fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult { 162 fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
143 s.emit_u32(self.as_u32()) 163 s.emit_u32(self.as_u32())
@@ -418,6 +438,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
418 let krate = self.tcx.hir().krate(); 438 let krate = self.tcx.hir().krate();
419 let vis = Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public }; 439 let vis = Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public };
420 self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.item.module, &krate.item.attrs, &vis); 440 self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.item.module, &krate.item.attrs, &vis);
441
442 // Proc-macro crates only export proc-macro items, which are looked
443 // up using `proc_macro_data`
444 if self.is_proc_macro {
445 return;
446 }
447
421 krate.visit_all_item_likes(&mut self.as_deep_visitor()); 448 krate.visit_all_item_likes(&mut self.as_deep_visitor());
422 for macro_def in krate.exported_macros { 449 for macro_def in krate.exported_macros {
423 self.visit_macro_def(macro_def); 450 self.visit_macro_def(macro_def);
@@ -426,11 +453,22 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
426 453
427 fn encode_def_path_table(&mut self) { 454 fn encode_def_path_table(&mut self) {
428 let table = self.tcx.hir().definitions().def_path_table(); 455 let table = self.tcx.hir().definitions().def_path_table();
429 for (def_index, def_key, def_path_hash) in table.enumerated_keys_and_path_hashes() { 456 if self.is_proc_macro {
430 let def_key = self.lazy(def_key); 457 for def_index in std::iter::once(CRATE_DEF_INDEX)
431 let def_path_hash = self.lazy(def_path_hash); 458 .chain(self.tcx.hir().krate().proc_macros.iter().map(|p| p.owner.local_def_index))
432 self.tables.def_keys.set(def_index, def_key); 459 {
433 self.tables.def_path_hashes.set(def_index, def_path_hash); 460 let def_key = self.lazy(table.def_key(def_index));
461 let def_path_hash = self.lazy(table.def_path_hash(def_index));
462 self.tables.def_keys.set(def_index, def_key);
463 self.tables.def_path_hashes.set(def_index, def_path_hash);
464 }
465 } else {
466 for (def_index, def_key, def_path_hash) in table.enumerated_keys_and_path_hashes() {
467 let def_key = self.lazy(def_key);
468 let def_path_hash = self.lazy(def_path_hash);
469 self.tables.def_keys.set(def_index, def_key);
470 self.tables.def_path_hashes.set(def_index, def_path_hash);
471 }
434 } 472 }
435 } 473 }
436 474
@@ -497,13 +535,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
497 self.lazy(adapted.iter().map(|rc| &**rc)) 535 self.lazy(adapted.iter().map(|rc| &**rc))
498 } 536 }
499 537
500 fn is_proc_macro(&self) -> bool {
501 self.tcx.sess.crate_types().contains(&CrateType::ProcMacro)
502 }
503
504 fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> { 538 fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
505 let is_proc_macro = self.is_proc_macro();
506
507 let mut i = self.position(); 539 let mut i = self.position();
508 540
509 // Encode the crate deps 541 // Encode the crate deps
@@ -575,15 +607,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
575 self.lazy(interpret_alloc_index) 607 self.lazy(interpret_alloc_index)
576 }; 608 };
577 609
578 i = self.position(); 610 // Encode the proc macro data. This affects 'tables',
579 let tables = self.tables.encode(&mut self.opaque); 611 // so we need to do this before we encode the tables
580 let tables_bytes = self.position() - i;
581
582 // Encode the proc macro data
583 i = self.position(); 612 i = self.position();
584 let proc_macro_data = self.encode_proc_macros(); 613 let proc_macro_data = self.encode_proc_macros();
585 let proc_macro_data_bytes = self.position() - i; 614 let proc_macro_data_bytes = self.position() - i;
586 615
616 i = self.position();
617 let tables = self.tables.encode(&mut self.opaque);
618 let tables_bytes = self.position() - i;
619
587 // Encode exported symbols info. This is prefetched in `encode_metadata` so we encode 620 // Encode exported symbols info. This is prefetched in `encode_metadata` so we encode
588 // this as late as possible to give the prefetching as much time as possible to complete. 621 // this as late as possible to give the prefetching as much time as possible to complete.
589 i = self.position(); 622 i = self.position();
@@ -624,18 +657,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
624 has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE), 657 has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
625 has_default_lib_allocator, 658 has_default_lib_allocator,
626 plugin_registrar_fn: tcx.plugin_registrar_fn(LOCAL_CRATE).map(|id| id.index), 659 plugin_registrar_fn: tcx.plugin_registrar_fn(LOCAL_CRATE).map(|id| id.index),
627 proc_macro_decls_static: if is_proc_macro {
628 let id = tcx.proc_macro_decls_static(LOCAL_CRATE).unwrap();
629 Some(id.index)
630 } else {
631 None
632 },
633 proc_macro_data, 660 proc_macro_data,
634 proc_macro_stability: if is_proc_macro {
635 tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX)).copied()
636 } else {
637 None
638 },
639 compiler_builtins: tcx.sess.contains_name(&attrs, sym::compiler_builtins), 661 compiler_builtins: tcx.sess.contains_name(&attrs, sym::compiler_builtins),
640 needs_allocator: tcx.sess.contains_name(&attrs, sym::needs_allocator), 662 needs_allocator: tcx.sess.contains_name(&attrs, sym::needs_allocator),
641 needs_panic_runtime: tcx.sess.contains_name(&attrs, sym::needs_panic_runtime), 663 needs_panic_runtime: tcx.sess.contains_name(&attrs, sym::needs_panic_runtime),
@@ -800,8 +822,13 @@ impl EncodeContext<'a, 'tcx> {
800 let def_id = local_def_id.to_def_id(); 822 let def_id = local_def_id.to_def_id();
801 debug!("EncodeContext::encode_info_for_mod({:?})", def_id); 823 debug!("EncodeContext::encode_info_for_mod({:?})", def_id);
802 824
803 let data = ModData { 825 // If we are encoding a proc-macro crates, `encode_info_for_mod` will
804 reexports: match tcx.module_exports(local_def_id) { 826 // only ever get called for the crate root. We still want to encode
827 // the crate root for consistency with other crates (some of the resolver
828 // code uses it). However, we skip encoding anything relating to child
829 // items - we encode information about proc-macros later on.
830 let reexports = if !self.is_proc_macro {
831 match tcx.module_exports(local_def_id) {
805 Some(exports) => { 832 Some(exports) => {
806 let hir = self.tcx.hir(); 833 let hir = self.tcx.hir();
807 self.lazy( 834 self.lazy(
@@ -811,7 +838,13 @@ impl EncodeContext<'a, 'tcx> {
811 ) 838 )
812 } 839 }
813 _ => Lazy::empty(), 840 _ => Lazy::empty(),
814 }, 841 }
842 } else {
843 Lazy::empty()
844 };
845
846 let data = ModData {
847 reexports,
815 expansion: tcx.hir().definitions().expansion_that_defined(local_def_id), 848 expansion: tcx.hir().definitions().expansion_that_defined(local_def_id),
816 }; 849 };
817 850
@@ -819,9 +852,13 @@ impl EncodeContext<'a, 'tcx> {
819 record!(self.tables.visibility[def_id] <- ty::Visibility::from_hir(vis, id, self.tcx)); 852 record!(self.tables.visibility[def_id] <- ty::Visibility::from_hir(vis, id, self.tcx));
820 record!(self.tables.span[def_id] <- self.tcx.def_span(def_id)); 853 record!(self.tables.span[def_id] <- self.tcx.def_span(def_id));
821 record!(self.tables.attributes[def_id] <- attrs); 854 record!(self.tables.attributes[def_id] <- attrs);
822 record!(self.tables.children[def_id] <- md.item_ids.iter().map(|item_id| { 855 if self.is_proc_macro {
823 tcx.hir().local_def_id(item_id.id).local_def_index 856 record!(self.tables.children[def_id] <- &[]);
824 })); 857 } else {
858 record!(self.tables.children[def_id] <- md.item_ids.iter().map(|item_id| {
859 tcx.hir().local_def_id(item_id.id).local_def_index
860 }));
861 }
825 self.encode_stability(def_id); 862 self.encode_stability(def_id);
826 self.encode_deprecation(def_id); 863 self.encode_deprecation(def_id);
827 } 864 }
@@ -1481,11 +1518,13 @@ impl EncodeContext<'a, 'tcx> {
1481 } 1518 }
1482 1519
1483 fn encode_native_libraries(&mut self) -> Lazy<[NativeLib]> { 1520 fn encode_native_libraries(&mut self) -> Lazy<[NativeLib]> {
1521 empty_proc_macro!(self);
1484 let used_libraries = self.tcx.native_libraries(LOCAL_CRATE); 1522 let used_libraries = self.tcx.native_libraries(LOCAL_CRATE);
1485 self.lazy(used_libraries.iter().cloned()) 1523 self.lazy(used_libraries.iter().cloned())
1486 } 1524 }
1487 1525
1488 fn encode_foreign_modules(&mut self) -> Lazy<[ForeignModule]> { 1526 fn encode_foreign_modules(&mut self) -> Lazy<[ForeignModule]> {
1527 empty_proc_macro!(self);
1489 let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE); 1528 let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE);
1490 self.lazy(foreign_modules.iter().cloned()) 1529 self.lazy(foreign_modules.iter().cloned())
1491 } 1530 }
@@ -1509,17 +1548,37 @@ impl EncodeContext<'a, 'tcx> {
1509 (syntax_contexts.encode(&mut self.opaque), expn_data_table.encode(&mut self.opaque)) 1548 (syntax_contexts.encode(&mut self.opaque), expn_data_table.encode(&mut self.opaque))
1510 } 1549 }
1511 1550
1512 fn encode_proc_macros(&mut self) -> Option<Lazy<[DefIndex]>> { 1551 fn encode_proc_macros(&mut self) -> Option<ProcMacroData> {
1513 let is_proc_macro = self.tcx.sess.crate_types().contains(&CrateType::ProcMacro); 1552 let is_proc_macro = self.tcx.sess.crate_types().contains(&CrateType::ProcMacro);
1514 if is_proc_macro { 1553 if is_proc_macro {
1515 let tcx = self.tcx; 1554 let tcx = self.tcx;
1516 Some(self.lazy(tcx.hir().krate().proc_macros.iter().map(|p| p.owner.local_def_index))) 1555 let hir = tcx.hir();
1556
1557 let proc_macro_decls_static = tcx.proc_macro_decls_static(LOCAL_CRATE).unwrap().index;
1558 let stability = tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX)).copied();
1559 let macros = self.lazy(hir.krate().proc_macros.iter().map(|p| p.owner.local_def_index));
1560
1561 // Normally, this information is encoded when we walk the items
1562 // defined in this crate. However, we skip doing that for proc-macro crates,
1563 // so we manually encode just the information that we need
1564 for proc_macro in &hir.krate().proc_macros {
1565 let id = proc_macro.owner.local_def_index;
1566 let span = self.lazy(hir.span(*proc_macro));
1567 // Proc-macros may have attributes like `#[allow_internal_unstable]`,
1568 // so downstream crates need access to them.
1569 let attrs = self.lazy(hir.attrs(*proc_macro));
1570 self.tables.span.set(id, span);
1571 self.tables.attributes.set(id, attrs);
1572 }
1573
1574 Some(ProcMacroData { proc_macro_decls_static, stability, macros })
1517 } else { 1575 } else {
1518 None 1576 None
1519 } 1577 }
1520 } 1578 }
1521 1579
1522 fn encode_crate_deps(&mut self) -> Lazy<[CrateDep]> { 1580 fn encode_crate_deps(&mut self) -> Lazy<[CrateDep]> {
1581 empty_proc_macro!(self);
1523 let crates = self.tcx.crates(); 1582 let crates = self.tcx.crates();
1524 1583
1525 let mut deps = crates 1584 let mut deps = crates
@@ -1555,18 +1614,21 @@ impl EncodeContext<'a, 'tcx> {
1555 } 1614 }
1556 1615
1557 fn encode_lib_features(&mut self) -> Lazy<[(Symbol, Option<Symbol>)]> { 1616 fn encode_lib_features(&mut self) -> Lazy<[(Symbol, Option<Symbol>)]> {
1617 empty_proc_macro!(self);
1558 let tcx = self.tcx; 1618 let tcx = self.tcx;
1559 let lib_features = tcx.lib_features(); 1619 let lib_features = tcx.lib_features();
1560 self.lazy(lib_features.to_vec()) 1620 self.lazy(lib_features.to_vec())
1561 } 1621 }
1562 1622
1563 fn encode_diagnostic_items(&mut self) -> Lazy<[(Symbol, DefIndex)]> { 1623 fn encode_diagnostic_items(&mut self) -> Lazy<[(Symbol, DefIndex)]> {
1624 empty_proc_macro!(self);
1564 let tcx = self.tcx; 1625 let tcx = self.tcx;
1565 let diagnostic_items = tcx.diagnostic_items(LOCAL_CRATE); 1626 let diagnostic_items = tcx.diagnostic_items(LOCAL_CRATE);
1566 self.lazy(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index))) 1627 self.lazy(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index)))
1567 } 1628 }
1568 1629
1569 fn encode_lang_items(&mut self) -> Lazy<[(DefIndex, usize)]> { 1630 fn encode_lang_items(&mut self) -> Lazy<[(DefIndex, usize)]> {
1631 empty_proc_macro!(self);
1570 let tcx = self.tcx; 1632 let tcx = self.tcx;
1571 let lang_items = tcx.lang_items(); 1633 let lang_items = tcx.lang_items();
1572 let lang_items = lang_items.items().iter(); 1634 let lang_items = lang_items.items().iter();
@@ -1581,12 +1643,14 @@ impl EncodeContext<'a, 'tcx> {
1581 } 1643 }
1582 1644
1583 fn encode_lang_items_missing(&mut self) -> Lazy<[lang_items::LangItem]> { 1645 fn encode_lang_items_missing(&mut self) -> Lazy<[lang_items::LangItem]> {
1646 empty_proc_macro!(self);
1584 let tcx = self.tcx; 1647 let tcx = self.tcx;
1585 self.lazy(&tcx.lang_items().missing) 1648 self.lazy(&tcx.lang_items().missing)
1586 } 1649 }
1587 1650
1588 /// Encodes an index, mapping each trait to its (local) implementations. 1651 /// Encodes an index, mapping each trait to its (local) implementations.
1589 fn encode_impls(&mut self) -> Lazy<[TraitImpls]> { 1652 fn encode_impls(&mut self) -> Lazy<[TraitImpls]> {
1653 empty_proc_macro!(self);
1590 debug!("EncodeContext::encode_impls()"); 1654 debug!("EncodeContext::encode_impls()");
1591 let tcx = self.tcx; 1655 let tcx = self.tcx;
1592 let mut visitor = ImplVisitor { tcx, impls: FxHashMap::default() }; 1656 let mut visitor = ImplVisitor { tcx, impls: FxHashMap::default() };
@@ -1625,6 +1689,7 @@ impl EncodeContext<'a, 'tcx> {
1625 &mut self, 1689 &mut self,
1626 exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportLevel)], 1690 exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportLevel)],
1627 ) -> Lazy<[(ExportedSymbol<'tcx>, SymbolExportLevel)]> { 1691 ) -> Lazy<[(ExportedSymbol<'tcx>, SymbolExportLevel)]> {
1692 empty_proc_macro!(self);
1628 // The metadata symbol name is special. It should not show up in 1693 // The metadata symbol name is special. It should not show up in
1629 // downstream crates. 1694 // downstream crates.
1630 let metadata_symbol_name = SymbolName::new(self.tcx, &metadata_symbol_name(self.tcx)); 1695 let metadata_symbol_name = SymbolName::new(self.tcx, &metadata_symbol_name(self.tcx));
@@ -1641,6 +1706,7 @@ impl EncodeContext<'a, 'tcx> {
1641 } 1706 }
1642 1707
1643 fn encode_dylib_dependency_formats(&mut self) -> Lazy<[Option<LinkagePreference>]> { 1708 fn encode_dylib_dependency_formats(&mut self) -> Lazy<[Option<LinkagePreference>]> {
1709 empty_proc_macro!(self);
1644 let formats = self.tcx.dependency_formats(LOCAL_CRATE); 1710 let formats = self.tcx.dependency_formats(LOCAL_CRATE);
1645 for (ty, arr) in formats.iter() { 1711 for (ty, arr) in formats.iter() {
1646 if *ty != CrateType::Dylib { 1712 if *ty != CrateType::Dylib {
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index ba540c9..1a12703 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -173,6 +173,29 @@ type SyntaxContextTable = Lazy<Table<u32, Lazy<SyntaxContextData>>>;
173type ExpnDataTable = Lazy<Table<u32, Lazy<ExpnData>>>; 173type ExpnDataTable = Lazy<Table<u32, Lazy<ExpnData>>>;
174 174
175#[derive(MetadataEncodable, MetadataDecodable)] 175#[derive(MetadataEncodable, MetadataDecodable)]
176crate struct ProcMacroData {
177 proc_macro_decls_static: DefIndex,
178 stability: Option<attr::Stability>,
179 macros: Lazy<[DefIndex]>,
180}
181
182/// Serialized metadata for a crate.
183/// When compiling a proc-macro crate, we encode many of
184/// the `Lazy<[T]>` fields as `Lazy::empty()`. This serves two purposes:
185///
186/// 1. We avoid performing unnecessary work. Proc-macro crates can only
187/// export proc-macros functions, which are compiled into a shared library.
188/// As a result, a large amount of the information we normally store
189/// (e.g. optimized MIR) is unneeded by downstream crates.
190/// 2. We avoid serializing invalid `CrateNum`s. When we deserialize
191/// a proc-macro crate, we don't load any of its dependencies (since we
192/// just need to invoke a native function from the shared library).
193/// This means that any foreign `CrateNum`s that we serialize cannot be
194/// deserialized, since we will not know how to map them into the current
195/// compilation session. If we were to serialize a proc-macro crate like
196/// a normal crate, much of what we serialized would be unusable in addition
197/// to being unused.
198#[derive(MetadataEncodable, MetadataDecodable)]
176crate struct CrateRoot<'tcx> { 199crate struct CrateRoot<'tcx> {
177 name: Symbol, 200 name: Symbol,
178 triple: TargetTriple, 201 triple: TargetTriple,
@@ -185,8 +208,6 @@ crate struct CrateRoot<'tcx> {
185 has_panic_handler: bool, 208 has_panic_handler: bool,
186 has_default_lib_allocator: bool, 209 has_default_lib_allocator: bool,
187 plugin_registrar_fn: Option<DefIndex>, 210 plugin_registrar_fn: Option<DefIndex>,
188 proc_macro_decls_static: Option<DefIndex>,
189 proc_macro_stability: Option<attr::Stability>,
190 211
191 crate_deps: Lazy<[CrateDep]>, 212 crate_deps: Lazy<[CrateDep]>,
192 dylib_dependency_formats: Lazy<[Option<LinkagePreference>]>, 213 dylib_dependency_formats: Lazy<[Option<LinkagePreference>]>,
@@ -198,12 +219,10 @@ crate struct CrateRoot<'tcx> {
198 foreign_modules: Lazy<[ForeignModule]>, 219 foreign_modules: Lazy<[ForeignModule]>,
199 impls: Lazy<[TraitImpls]>, 220 impls: Lazy<[TraitImpls]>,
200 interpret_alloc_index: Lazy<[u32]>, 221 interpret_alloc_index: Lazy<[u32]>,
222 proc_macro_data: Option<ProcMacroData>,
201 223
202 tables: LazyTables<'tcx>, 224 tables: LazyTables<'tcx>,
203 225
204 /// The DefIndex's of any proc macros declared by this crate.
205 proc_macro_data: Option<Lazy<[DefIndex]>>,
206
207 exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]), 226 exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]),
208 227
209 syntax_contexts: SyntaxContextTable, 228 syntax_contexts: SyntaxContextTable,
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 492afa5..d6cf68a 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -682,25 +682,31 @@ pub enum BorrowKind {
682 /// implicit closure bindings. It is needed when the closure 682 /// implicit closure bindings. It is needed when the closure
683 /// is borrowing or mutating a mutable referent, e.g.: 683 /// is borrowing or mutating a mutable referent, e.g.:
684 /// 684 ///
685 /// let x: &mut isize = ...; 685 /// ```
686 /// let y = || *x += 5; 686 /// let x: &mut isize = ...;
687 /// let y = || *x += 5;
688 /// ```
687 /// 689 ///
688 /// If we were to try to translate this closure into a more explicit 690 /// If we were to try to translate this closure into a more explicit
689 /// form, we'd encounter an error with the code as written: 691 /// form, we'd encounter an error with the code as written:
690 /// 692 ///
691 /// struct Env { x: & &mut isize } 693 /// ```
692 /// let x: &mut isize = ...; 694 /// struct Env { x: & &mut isize }
693 /// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn 695 /// let x: &mut isize = ...;
694 /// fn fn_ptr(env: &mut Env) { **env.x += 5; } 696 /// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn
697 /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
698 /// ```
695 /// 699 ///
696 /// This is then illegal because you cannot mutate a `&mut` found 700 /// This is then illegal because you cannot mutate a `&mut` found
697 /// in an aliasable location. To solve, you'd have to translate with 701 /// in an aliasable location. To solve, you'd have to translate with
698 /// an `&mut` borrow: 702 /// an `&mut` borrow:
699 /// 703 ///
700 /// struct Env { x: & &mut isize } 704 /// ```
701 /// let x: &mut isize = ...; 705 /// struct Env { x: & &mut isize }
702 /// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x 706 /// let x: &mut isize = ...;
703 /// fn fn_ptr(env: &mut Env) { **env.x += 5; } 707 /// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
708 /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
709 /// ```
704 /// 710 ///
705 /// Now the assignment to `**env.x` is legal, but creating a 711 /// Now the assignment to `**env.x` is legal, but creating a
706 /// mutable pointer to `x` is not because `x` is not mutable. We 712 /// mutable pointer to `x` is not because `x` is not mutable. We
diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs
index aa88719..0f04ead 100644
--- a/compiler/rustc_mir/src/transform/const_prop.rs
+++ b/compiler/rustc_mir/src/transform/const_prop.rs
@@ -1046,9 +1046,9 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
1046 fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) { 1046 fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) {
1047 self.super_operand(operand, location); 1047 self.super_operand(operand, location);
1048 1048
1049 // Only const prop copies and moves on `mir_opt_level=3` as doing so 1049 // Only const prop copies and moves on `mir_opt_level=2` as doing so
1050 // currently increases compile time. 1050 // currently slightly increases compile time in some cases.
1051 if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 3 { 1051 if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
1052 self.propagate_operand(operand) 1052 self.propagate_operand(operand)
1053 } 1053 }
1054 } 1054 }
@@ -1246,8 +1246,8 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
1246 | TerminatorKind::InlineAsm { .. } => {} 1246 | TerminatorKind::InlineAsm { .. } => {}
1247 // Every argument in our function calls have already been propagated in `visit_operand`. 1247 // Every argument in our function calls have already been propagated in `visit_operand`.
1248 // 1248 //
1249 // NOTE: because LLVM codegen gives performance regressions with it, so this is gated 1249 // NOTE: because LLVM codegen gives slight performance regressions with it, so this is
1250 // on `mir_opt_level=3`. 1250 // gated on `mir_opt_level=2`.
1251 TerminatorKind::Call { .. } => {} 1251 TerminatorKind::Call { .. } => {}
1252 } 1252 }
1253 1253
diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs
index a622de9..850cafc 100644
--- a/compiler/rustc_mir/src/transform/mod.rs
+++ b/compiler/rustc_mir/src/transform/mod.rs
@@ -36,7 +36,6 @@ pub mod match_branches;
36pub mod no_landing_pads; 36pub mod no_landing_pads;
37pub mod nrvo; 37pub mod nrvo;
38pub mod promote_consts; 38pub mod promote_consts;
39pub mod qualify_min_const_fn;
40pub mod remove_noop_landing_pads; 39pub mod remove_noop_landing_pads;
41pub mod remove_unneeded_drops; 40pub mod remove_unneeded_drops;
42pub mod required_consts; 41pub mod required_consts;
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 21bbdc9..d59dd40 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -7,7 +7,7 @@
7#![feature(or_patterns)] 7#![feature(or_patterns)]
8 8
9use rustc_ast as ast; 9use rustc_ast as ast;
10use rustc_ast::token::{self, DelimToken, Nonterminal, Token, TokenKind}; 10use rustc_ast::token::{self, Nonterminal, Token, TokenKind};
11use rustc_ast::tokenstream::{self, Spacing, TokenStream, TokenTree}; 11use rustc_ast::tokenstream::{self, Spacing, TokenStream, TokenTree};
12use rustc_ast_pretty::pprust; 12use rustc_ast_pretty::pprust;
13use rustc_data_structures::sync::Lrc; 13use rustc_data_structures::sync::Lrc;
@@ -299,7 +299,7 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
299 // FIXME(#43081): Avoid this pretty-print + reparse hack 299 // FIXME(#43081): Avoid this pretty-print + reparse hack
300 let source = pprust::nonterminal_to_string(nt); 300 let source = pprust::nonterminal_to_string(nt);
301 let filename = FileName::macro_expansion_source_code(&source); 301 let filename = FileName::macro_expansion_source_code(&source);
302 let tokens_for_real = parse_stream_from_source_str(filename, source, sess, Some(span)); 302 let reparsed_tokens = parse_stream_from_source_str(filename, source, sess, Some(span));
303 303
304 // During early phases of the compiler the AST could get modified 304 // During early phases of the compiler the AST could get modified
305 // directly (e.g., attributes added or removed) and the internal cache 305 // directly (e.g., attributes added or removed) and the internal cache
@@ -325,7 +325,7 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
325 // modifications, including adding/removing typically non-semantic 325 // modifications, including adding/removing typically non-semantic
326 // tokens such as extra braces and commas, don't happen. 326 // tokens such as extra braces and commas, don't happen.
327 if let Some(tokens) = tokens { 327 if let Some(tokens) = tokens {
328 if tokenstream_probably_equal_for_proc_macro(&tokens, &tokens_for_real, sess) { 328 if tokenstream_probably_equal_for_proc_macro(&tokens, &reparsed_tokens, sess) {
329 return tokens; 329 return tokens;
330 } 330 }
331 info!( 331 info!(
@@ -333,9 +333,9 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
333 going with stringified version" 333 going with stringified version"
334 ); 334 );
335 info!("cached tokens: {:?}", tokens); 335 info!("cached tokens: {:?}", tokens);
336 info!("reparsed tokens: {:?}", tokens_for_real); 336 info!("reparsed tokens: {:?}", reparsed_tokens);
337 } 337 }
338 tokens_for_real 338 reparsed_tokens
339} 339}
340 340
341// See comments in `Nonterminal::to_tokenstream` for why we care about 341// See comments in `Nonterminal::to_tokenstream` for why we care about
@@ -344,8 +344,8 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
344// This is otherwise the same as `eq_unspanned`, only recursing with a 344// This is otherwise the same as `eq_unspanned`, only recursing with a
345// different method. 345// different method.
346pub fn tokenstream_probably_equal_for_proc_macro( 346pub fn tokenstream_probably_equal_for_proc_macro(
347 first: &TokenStream, 347 tokens: &TokenStream,
348 other: &TokenStream, 348 reparsed_tokens: &TokenStream,
349 sess: &ParseSess, 349 sess: &ParseSess,
350) -> bool { 350) -> bool {
351 // When checking for `probably_eq`, we ignore certain tokens that aren't 351 // When checking for `probably_eq`, we ignore certain tokens that aren't
@@ -359,9 +359,6 @@ pub fn tokenstream_probably_equal_for_proc_macro(
359 // The pretty printer tends to add trailing commas to 359 // The pretty printer tends to add trailing commas to
360 // everything, and in particular, after struct fields. 360 // everything, and in particular, after struct fields.
361 | token::Comma 361 | token::Comma
362 // The pretty printer emits `NoDelim` as whitespace.
363 | token::OpenDelim(DelimToken::NoDelim)
364 | token::CloseDelim(DelimToken::NoDelim)
365 // The pretty printer collapses many semicolons into one. 362 // The pretty printer collapses many semicolons into one.
366 | token::Semi 363 | token::Semi
367 // We don't preserve leading `|` tokens in patterns, so 364 // We don't preserve leading `|` tokens in patterns, so
@@ -460,10 +457,11 @@ pub fn tokenstream_probably_equal_for_proc_macro(
460 457
461 // Break tokens after we expand any nonterminals, so that we break tokens 458 // Break tokens after we expand any nonterminals, so that we break tokens
462 // that are produced as a result of nonterminal expansion. 459 // that are produced as a result of nonterminal expansion.
463 let t1 = first.trees().filter(semantic_tree).flat_map(expand_nt).flat_map(break_tokens); 460 let tokens = tokens.trees().filter(semantic_tree).flat_map(expand_nt).flat_map(break_tokens);
464 let t2 = other.trees().filter(semantic_tree).flat_map(expand_nt).flat_map(break_tokens); 461 let reparsed_tokens =
462 reparsed_tokens.trees().filter(semantic_tree).flat_map(expand_nt).flat_map(break_tokens);
465 463
466 t1.eq_by(t2, |t1, t2| tokentree_probably_equal_for_proc_macro(&t1, &t2, sess)) 464 tokens.eq_by(reparsed_tokens, |t, rt| tokentree_probably_equal_for_proc_macro(&t, &rt, sess))
467} 465}
468 466
469// See comments in `Nonterminal::to_tokenstream` for why we care about 467// See comments in `Nonterminal::to_tokenstream` for why we care about
@@ -472,16 +470,20 @@ pub fn tokenstream_probably_equal_for_proc_macro(
472// This is otherwise the same as `eq_unspanned`, only recursing with a 470// This is otherwise the same as `eq_unspanned`, only recursing with a
473// different method. 471// different method.
474pub fn tokentree_probably_equal_for_proc_macro( 472pub fn tokentree_probably_equal_for_proc_macro(
475 first: &TokenTree, 473 token: &TokenTree,
476 other: &TokenTree, 474 reparsed_token: &TokenTree,
477 sess: &ParseSess, 475 sess: &ParseSess,
478) -> bool { 476) -> bool {
479 match (first, other) { 477 match (token, reparsed_token) {
480 (TokenTree::Token(token), TokenTree::Token(token2)) => { 478 (TokenTree::Token(token), TokenTree::Token(reparsed_token)) => {
481 token_probably_equal_for_proc_macro(token, token2) 479 token_probably_equal_for_proc_macro(token, reparsed_token)
482 } 480 }
483 (TokenTree::Delimited(_, delim, tts), TokenTree::Delimited(_, delim2, tts2)) => { 481 (
484 delim == delim2 && tokenstream_probably_equal_for_proc_macro(&tts, &tts2, sess) 482 TokenTree::Delimited(_, delim, tokens),
483 TokenTree::Delimited(_, reparsed_delim, reparsed_tokens),
484 ) => {
485 delim == reparsed_delim
486 && tokenstream_probably_equal_for_proc_macro(tokens, reparsed_tokens, sess)
485 } 487 }
486 _ => false, 488 _ => false,
487 } 489 }
diff --git a/compiler/rustc_target/src/spec/windows_gnu_base.rs b/compiler/rustc_target/src/spec/windows_gnu_base.rs
index a864918..0234ff5 100644
--- a/compiler/rustc_target/src/spec/windows_gnu_base.rs
+++ b/compiler/rustc_target/src/spec/windows_gnu_base.rs
@@ -23,6 +23,7 @@ pub fn opts() -> TargetOptions {
23 "-lmsvcrt".to_string(), 23 "-lmsvcrt".to_string(),
24 "-lmingwex".to_string(), 24 "-lmingwex".to_string(),
25 "-lmingw32".to_string(), 25 "-lmingw32".to_string(),
26 "-lgcc".to_string(), // alas, mingw* libraries above depend on libgcc
26 // mingw's msvcrt is a weird hybrid import library and static library. 27 // mingw's msvcrt is a weird hybrid import library and static library.
27 // And it seems that the linker fails to use import symbols from msvcrt 28 // And it seems that the linker fails to use import symbols from msvcrt
28 // that are required from functions in msvcrt in certain cases. For example 29 // that are required from functions in msvcrt in certain cases. For example
@@ -41,8 +42,6 @@ pub fn opts() -> TargetOptions {
41 // the shared libgcc_s-dw2-1.dll. This is required to support 42 // the shared libgcc_s-dw2-1.dll. This is required to support
42 // unwinding across DLL boundaries. 43 // unwinding across DLL boundaries.
43 "-lgcc_s".to_string(), 44 "-lgcc_s".to_string(),
44 "-lgcc".to_string(),
45 "-lkernel32".to_string(),
46 ]; 45 ];
47 late_link_args_dynamic.insert(LinkerFlavor::Gcc, dynamic_unwind_libs.clone()); 46 late_link_args_dynamic.insert(LinkerFlavor::Gcc, dynamic_unwind_libs.clone());
48 late_link_args_dynamic.insert(LinkerFlavor::Lld(LldFlavor::Ld), dynamic_unwind_libs); 47 late_link_args_dynamic.insert(LinkerFlavor::Lld(LldFlavor::Ld), dynamic_unwind_libs);
@@ -54,10 +53,6 @@ pub fn opts() -> TargetOptions {
54 // boundaries when unwinding across FFI boundaries. 53 // boundaries when unwinding across FFI boundaries.
55 "-lgcc_eh".to_string(), 54 "-lgcc_eh".to_string(),
56 "-l:libpthread.a".to_string(), 55 "-l:libpthread.a".to_string(),
57 "-lgcc".to_string(),
58 // libpthread depends on libmsvcrt, so we need to link it *again*.
59 "-lmsvcrt".to_string(),
60 "-lkernel32".to_string(),
61 ]; 56 ];
62 late_link_args_static.insert(LinkerFlavor::Gcc, static_unwind_libs.clone()); 57 late_link_args_static.insert(LinkerFlavor::Gcc, static_unwind_libs.clone());
63 late_link_args_static.insert(LinkerFlavor::Lld(LldFlavor::Ld), static_unwind_libs); 58 late_link_args_static.insert(LinkerFlavor::Lld(LldFlavor::Ld), static_unwind_libs);
diff --git a/library/alloc/benches/vec.rs b/library/alloc/benches/vec.rs
index 687efa8..789ae3a 100644
--- a/library/alloc/benches/vec.rs
+++ b/library/alloc/benches/vec.rs
@@ -1,4 +1,4 @@
1use rand::prelude::*; 1use rand::RngCore;
2use std::iter::{repeat, FromIterator}; 2use std::iter::{repeat, FromIterator};
3use test::{black_box, Bencher}; 3use test::{black_box, Bencher};
4 4
diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs
index 939f132..378c8af 100644
--- a/library/core/tests/num/mod.rs
+++ b/library/core/tests/num/mod.rs
@@ -634,14 +634,18 @@ assume_usize_width! {
634macro_rules! test_float { 634macro_rules! test_float {
635 ($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr) => { 635 ($modname: ident, $fty: ty, $inf: expr, $neginf: expr, $nan: expr) => {
636 mod $modname { 636 mod $modname {
637 // FIXME(nagisa): these tests should test for sign of -0.0
638 #[test] 637 #[test]
639 fn min() { 638 fn min() {
640 assert_eq!((0.0 as $fty).min(0.0), 0.0); 639 assert_eq!((0.0 as $fty).min(0.0), 0.0);
640 assert!((0.0 as $fty).min(0.0).is_sign_positive());
641 assert_eq!((-0.0 as $fty).min(-0.0), -0.0); 641 assert_eq!((-0.0 as $fty).min(-0.0), -0.0);
642 assert!((-0.0 as $fty).min(-0.0).is_sign_negative());
642 assert_eq!((9.0 as $fty).min(9.0), 9.0); 643 assert_eq!((9.0 as $fty).min(9.0), 9.0);
643 assert_eq!((-9.0 as $fty).min(0.0), -9.0); 644 assert_eq!((-9.0 as $fty).min(0.0), -9.0);
644 assert_eq!((0.0 as $fty).min(9.0), 0.0); 645 assert_eq!((0.0 as $fty).min(9.0), 0.0);
646 assert!((0.0 as $fty).min(9.0).is_sign_positive());
647 assert_eq!((-0.0 as $fty).min(9.0), -0.0);
648 assert!((-0.0 as $fty).min(9.0).is_sign_negative());
645 assert_eq!((-0.0 as $fty).min(-9.0), -9.0); 649 assert_eq!((-0.0 as $fty).min(-9.0), -9.0);
646 assert_eq!(($inf as $fty).min(9.0), 9.0); 650 assert_eq!(($inf as $fty).min(9.0), 9.0);
647 assert_eq!((9.0 as $fty).min($inf), 9.0); 651 assert_eq!((9.0 as $fty).min($inf), 9.0);
@@ -660,11 +664,19 @@ macro_rules! test_float {
660 #[test] 664 #[test]
661 fn max() { 665 fn max() {
662 assert_eq!((0.0 as $fty).max(0.0), 0.0); 666 assert_eq!((0.0 as $fty).max(0.0), 0.0);
667 assert!((0.0 as $fty).max(0.0).is_sign_positive());
663 assert_eq!((-0.0 as $fty).max(-0.0), -0.0); 668 assert_eq!((-0.0 as $fty).max(-0.0), -0.0);
669 assert!((-0.0 as $fty).max(-0.0).is_sign_negative());
664 assert_eq!((9.0 as $fty).max(9.0), 9.0); 670 assert_eq!((9.0 as $fty).max(9.0), 9.0);
665 assert_eq!((-9.0 as $fty).max(0.0), 0.0); 671 assert_eq!((-9.0 as $fty).max(0.0), 0.0);
672 assert!((-9.0 as $fty).max(0.0).is_sign_positive());
673 assert_eq!((-9.0 as $fty).max(-0.0), -0.0);
674 assert!((-9.0 as $fty).max(-0.0).is_sign_negative());
666 assert_eq!((0.0 as $fty).max(9.0), 9.0); 675 assert_eq!((0.0 as $fty).max(9.0), 9.0);
676 assert_eq!((0.0 as $fty).max(-9.0), 0.0);
677 assert!((0.0 as $fty).max(-9.0).is_sign_positive());
667 assert_eq!((-0.0 as $fty).max(-9.0), -0.0); 678 assert_eq!((-0.0 as $fty).max(-9.0), -0.0);
679 assert!((-0.0 as $fty).max(-9.0).is_sign_negative());
668 assert_eq!(($inf as $fty).max(9.0), $inf); 680 assert_eq!(($inf as $fty).max(9.0), $inf);
669 assert_eq!((9.0 as $fty).max($inf), $inf); 681 assert_eq!((9.0 as $fty).max($inf), $inf);
670 assert_eq!(($inf as $fty).max(-9.0), $inf); 682 assert_eq!(($inf as $fty).max(-9.0), $inf);
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 61d71d5..1bb835e 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -1102,6 +1102,16 @@ where
1102/// documentation for more. 1102/// documentation for more.
1103/// 1103///
1104/// [`iter`]: HashMap::iter 1104/// [`iter`]: HashMap::iter
1105///
1106/// # Example
1107///
1108/// ```
1109/// use std::collections::HashMap;
1110///
1111/// let mut map = HashMap::new();
1112/// map.insert("a", 1);
1113/// let iter = map.iter();
1114/// ```
1105#[stable(feature = "rust1", since = "1.0.0")] 1115#[stable(feature = "rust1", since = "1.0.0")]
1106pub struct Iter<'a, K: 'a, V: 'a> { 1116pub struct Iter<'a, K: 'a, V: 'a> {
1107 base: base::Iter<'a, K, V>, 1117 base: base::Iter<'a, K, V>,
@@ -1129,6 +1139,16 @@ impl<K: Debug, V: Debug> fmt::Debug for Iter<'_, K, V> {
1129/// documentation for more. 1139/// documentation for more.
1130/// 1140///
1131/// [`iter_mut`]: HashMap::iter_mut 1141/// [`iter_mut`]: HashMap::iter_mut
1142///
1143/// # Example
1144///
1145/// ```
1146/// use std::collections::HashMap;
1147///
1148/// let mut map = HashMap::new();
1149/// map.insert("a", 1);
1150/// let iter = map.iter_mut();
1151/// ```
1132#[stable(feature = "rust1", since = "1.0.0")] 1152#[stable(feature = "rust1", since = "1.0.0")]
1133pub struct IterMut<'a, K: 'a, V: 'a> { 1153pub struct IterMut<'a, K: 'a, V: 'a> {
1134 base: base::IterMut<'a, K, V>, 1154 base: base::IterMut<'a, K, V>,
@@ -1148,6 +1168,16 @@ impl<'a, K, V> IterMut<'a, K, V> {
1148/// (provided by the `IntoIterator` trait). See its documentation for more. 1168/// (provided by the `IntoIterator` trait). See its documentation for more.
1149/// 1169///
1150/// [`into_iter`]: IntoIterator::into_iter 1170/// [`into_iter`]: IntoIterator::into_iter
1171///
1172/// # Example
1173///
1174/// ```
1175/// use std::collections::HashMap;
1176///
1177/// let mut map = HashMap::new();
1178/// map.insert("a", 1);
1179/// let iter = map.into_iter();
1180/// ```
1151#[stable(feature = "rust1", since = "1.0.0")] 1181#[stable(feature = "rust1", since = "1.0.0")]
1152pub struct IntoIter<K, V> { 1182pub struct IntoIter<K, V> {
1153 base: base::IntoIter<K, V>, 1183 base: base::IntoIter<K, V>,
@@ -1167,6 +1197,16 @@ impl<K, V> IntoIter<K, V> {
1167/// documentation for more. 1197/// documentation for more.
1168/// 1198///
1169/// [`keys`]: HashMap::keys 1199/// [`keys`]: HashMap::keys
1200///
1201/// # Example
1202///
1203/// ```
1204/// use std::collections::HashMap;
1205///
1206/// let mut map = HashMap::new();
1207/// map.insert("a", 1);
1208/// let iter_keys = map.keys();
1209/// ```
1170#[stable(feature = "rust1", since = "1.0.0")] 1210#[stable(feature = "rust1", since = "1.0.0")]
1171pub struct Keys<'a, K: 'a, V: 'a> { 1211pub struct Keys<'a, K: 'a, V: 'a> {
1172 inner: Iter<'a, K, V>, 1212 inner: Iter<'a, K, V>,
@@ -1194,6 +1234,16 @@ impl<K: Debug, V> fmt::Debug for Keys<'_, K, V> {
1194/// documentation for more. 1234/// documentation for more.
1195/// 1235///
1196/// [`values`]: HashMap::values 1236/// [`values`]: HashMap::values
1237///
1238/// # Example
1239///
1240/// ```
1241/// use std::collections::HashMap;
1242///
1243/// let mut map = HashMap::new();
1244/// map.insert("a", 1);
1245/// let iter_values = map.values();
1246/// ```
1197#[stable(feature = "rust1", since = "1.0.0")] 1247#[stable(feature = "rust1", since = "1.0.0")]
1198pub struct Values<'a, K: 'a, V: 'a> { 1248pub struct Values<'a, K: 'a, V: 'a> {
1199 inner: Iter<'a, K, V>, 1249 inner: Iter<'a, K, V>,
@@ -1221,6 +1271,16 @@ impl<K, V: Debug> fmt::Debug for Values<'_, K, V> {
1221/// documentation for more. 1271/// documentation for more.
1222/// 1272///
1223/// [`drain`]: HashMap::drain 1273/// [`drain`]: HashMap::drain
1274///
1275/// # Example
1276///
1277/// ```
1278/// use std::collections::HashMap;
1279///
1280/// let mut map = HashMap::new();
1281/// map.insert("a", 1);
1282/// let iter = map.drain();
1283/// ```
1224#[stable(feature = "drain", since = "1.6.0")] 1284#[stable(feature = "drain", since = "1.6.0")]
1225pub struct Drain<'a, K: 'a, V: 'a> { 1285pub struct Drain<'a, K: 'a, V: 'a> {
1226 base: base::Drain<'a, K, V>, 1286 base: base::Drain<'a, K, V>,
@@ -1239,6 +1299,18 @@ impl<'a, K, V> Drain<'a, K, V> {
1239/// This `struct` is created by the [`drain_filter`] method on [`HashMap`]. 1299/// This `struct` is created by the [`drain_filter`] method on [`HashMap`].
1240/// 1300///
1241/// [`drain_filter`]: HashMap::drain_filter 1301/// [`drain_filter`]: HashMap::drain_filter
1302///
1303/// # Example
1304///
1305/// ```
1306/// #![feature(hash_drain_filter)]
1307///
1308/// use std::collections::HashMap;
1309///
1310/// let mut map = HashMap::new();
1311/// map.insert("a", 1);
1312/// let iter = map.drain_filter(|_k, v| *v % 2 == 0);
1313/// ```
1242#[unstable(feature = "hash_drain_filter", issue = "59618")] 1314#[unstable(feature = "hash_drain_filter", issue = "59618")]
1243pub struct DrainFilter<'a, K, V, F> 1315pub struct DrainFilter<'a, K, V, F>
1244where 1316where
@@ -1253,6 +1325,16 @@ where
1253/// documentation for more. 1325/// documentation for more.
1254/// 1326///
1255/// [`values_mut`]: HashMap::values_mut 1327/// [`values_mut`]: HashMap::values_mut
1328///
1329/// # Example
1330///
1331/// ```
1332/// use std::collections::HashMap;
1333///
1334/// let mut map = HashMap::new();
1335/// map.insert("a", 1);
1336/// let iter_values = map.values_mut();
1337/// ```
1256#[stable(feature = "map_values_mut", since = "1.10.0")] 1338#[stable(feature = "map_values_mut", since = "1.10.0")]
1257pub struct ValuesMut<'a, K: 'a, V: 'a> { 1339pub struct ValuesMut<'a, K: 'a, V: 'a> {
1258 inner: IterMut<'a, K, V>, 1340 inner: IterMut<'a, K, V>,
@@ -1264,6 +1346,18 @@ pub struct ValuesMut<'a, K: 'a, V: 'a> {
1264/// See its documentation for more. 1346/// See its documentation for more.
1265/// 1347///
1266/// [`into_keys`]: HashMap::into_keys 1348/// [`into_keys`]: HashMap::into_keys
1349///
1350/// # Example
1351///
1352/// ```
1353/// #![feature(map_into_keys_values)]
1354///
1355/// use std::collections::HashMap;
1356///
1357/// let mut map = HashMap::new();
1358/// map.insert("a", 1);
1359/// let iter_keys = map.into_keys();
1360/// ```
1267#[unstable(feature = "map_into_keys_values", issue = "75294")] 1361#[unstable(feature = "map_into_keys_values", issue = "75294")]
1268pub struct IntoKeys<K, V> { 1362pub struct IntoKeys<K, V> {
1269 inner: IntoIter<K, V>, 1363 inner: IntoIter<K, V>,
@@ -1275,6 +1369,18 @@ pub struct IntoKeys<K, V> {
1275/// See its documentation for more. 1369/// See its documentation for more.
1276/// 1370///
1277/// [`into_values`]: HashMap::into_values 1371/// [`into_values`]: HashMap::into_values
1372///
1373/// # Example
1374///
1375/// ```
1376/// #![feature(map_into_keys_values)]
1377///
1378/// use std::collections::HashMap;
1379///
1380/// let mut map = HashMap::new();
1381/// map.insert("a", 1);
1382/// let iter_keys = map.into_values();
1383/// ```
1278#[unstable(feature = "map_into_keys_values", issue = "75294")] 1384#[unstable(feature = "map_into_keys_values", issue = "75294")]
1279pub struct IntoValues<K, V> { 1385pub struct IntoValues<K, V> {
1280 inner: IntoIter<K, V>, 1386 inner: IntoIter<K, V>,
@@ -1285,7 +1391,6 @@ pub struct IntoValues<K, V> {
1285/// See the [`HashMap::raw_entry_mut`] docs for usage examples. 1391/// See the [`HashMap::raw_entry_mut`] docs for usage examples.
1286/// 1392///
1287/// [`HashMap::raw_entry_mut`]: HashMap::raw_entry_mut 1393/// [`HashMap::raw_entry_mut`]: HashMap::raw_entry_mut
1288
1289#[unstable(feature = "hash_raw_entry", issue = "56167")] 1394#[unstable(feature = "hash_raw_entry", issue = "56167")]
1290pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> { 1395pub struct RawEntryBuilderMut<'a, K: 'a, V: 'a, S: 'a> {
1291 map: &'a mut HashMap<K, V, S>, 1396 map: &'a mut HashMap<K, V, S>,
diff --git a/src/tools/cargo b/src/tools/cargo
Subproject 8777a6b1e8834899f51b7e09cc9b8d85b241711 Subproject 05c611ae3c4255b7a2bcf4fcfa65b20286a0783
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 58112ac..c3ff34e 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -6,6 +6,7 @@
6#![feature(concat_idents)] 6#![feature(concat_idents)]
7#![feature(crate_visibility_modifier)] 7#![feature(crate_visibility_modifier)]
8#![feature(drain_filter)] 8#![feature(drain_filter)]
9#![feature(in_band_lifetimes)]
9#![feature(or_patterns)] 10#![feature(or_patterns)]
10#![feature(rustc_private)] 11#![feature(rustc_private)]
11#![feature(stmt_expr_attributes)] 12#![feature(stmt_expr_attributes)]
diff --git a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
index 1ad184d..e5f7cc5 100644
--- a/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_const_for_fn.rs
@@ -4,7 +4,7 @@ use rustc_hir::intravisit::FnKind;
4use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId}; 4use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId};
5use rustc_lint::{LateContext, LateLintPass}; 5use rustc_lint::{LateContext, LateLintPass};
6use rustc_middle::lint::in_external_macro; 6use rustc_middle::lint::in_external_macro;
7use rustc_mir::transform::qualify_min_const_fn::is_min_const_fn; 7use crate::utils::qualify_min_const_fn::is_min_const_fn;
8use rustc_session::{declare_lint_pass, declare_tool_lint}; 8use rustc_session::{declare_lint_pass, declare_tool_lint};
9use rustc_span::Span; 9use rustc_span::Span;
10use rustc_typeck::hir_ty_to_ty; 10use rustc_typeck::hir_ty_to_ty;
diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs
index ea52741..96d9905 100644
--- a/src/tools/clippy/clippy_lints/src/utils/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs
@@ -20,6 +20,7 @@ pub mod paths;
20pub mod ptr; 20pub mod ptr;
21pub mod sugg; 21pub mod sugg;
22pub mod usage; 22pub mod usage;
23pub mod qualify_min_const_fn;
23 24
24pub use self::attrs::*; 25pub use self::attrs::*;
25pub use self::diagnostics::*; 26pub use self::diagnostics::*;
diff --git a/compiler/rustc_mir/src/transform/qualify_min_const_fn.rs b/src/tools/clippy/clippy_lints/src/utils/qualify_min_const_fn.rs
index f15a7f7..6809b1f 100644
--- a/compiler/rustc_mir/src/transform/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/qualify_min_const_fn.rs
@@ -3,7 +3,7 @@ use rustc_hir::def_id::DefId;
3use rustc_middle::mir::*; 3use rustc_middle::mir::*;
4use rustc_middle::ty::subst::GenericArgKind; 4use rustc_middle::ty::subst::GenericArgKind;
5use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt}; 5use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt};
6use rustc_span::symbol::{sym, Symbol}; 6use rustc_span::symbol::{sym};
7use rustc_span::Span; 7use rustc_span::Span;
8use rustc_target::spec::abi::Abi::RustIntrinsic; 8use rustc_target::spec::abi::Abi::RustIntrinsic;
9use std::borrow::Cow; 9use std::borrow::Cow;
@@ -11,14 +11,6 @@ use std::borrow::Cow;
11type McfResult = Result<(), (Span, Cow<'static, str>)>; 11type McfResult = Result<(), (Span, Cow<'static, str>)>;
12 12
13pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -> McfResult { 13pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -> McfResult {
14 // Prevent const trait methods from being annotated as `stable`.
15 if tcx.features().staged_api {
16 let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
17 if crate::const_eval::is_parent_const_impl_raw(tcx, hir_id) {
18 return Err((body.span, "trait methods cannot be stable const fn".into()));
19 }
20 }
21
22 let mut current = def_id; 14 let mut current = def_id;
23 loop { 15 loop {
24 let predicates = tcx.predicates_of(current); 16 let predicates = tcx.predicates_of(current);
@@ -32,27 +24,20 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
32 | ty::PredicateAtom::ConstEquate(..) 24 | ty::PredicateAtom::ConstEquate(..)
33 | ty::PredicateAtom::TypeWellFormedFromEnv(..) => continue, 25 | ty::PredicateAtom::TypeWellFormedFromEnv(..) => continue,
34 ty::PredicateAtom::ObjectSafe(_) => { 26 ty::PredicateAtom::ObjectSafe(_) => {
35 bug!("object safe predicate on function: {:#?}", predicate) 27 panic!("object safe predicate on function: {:#?}", predicate)
36 } 28 }
37 ty::PredicateAtom::ClosureKind(..) => { 29 ty::PredicateAtom::ClosureKind(..) => {
38 bug!("closure kind predicate on function: {:#?}", predicate) 30 panic!("closure kind predicate on function: {:#?}", predicate)
39 } 31 }
40 ty::PredicateAtom::Subtype(_) => { 32 ty::PredicateAtom::Subtype(_) => {
41 bug!("subtype predicate on function: {:#?}", predicate) 33 panic!("subtype predicate on function: {:#?}", predicate)
42 } 34 }
43 ty::PredicateAtom::Trait(pred, constness) => { 35 ty::PredicateAtom::Trait(pred, _) => {
44 if Some(pred.def_id()) == tcx.lang_items().sized_trait() { 36 if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
45 continue; 37 continue;
46 } 38 }
47 match pred.self_ty().kind() { 39 match pred.self_ty().kind() {
48 ty::Param(ref p) => { 40 ty::Param(ref p) => {
49 // Allow `T: ?const Trait`
50 if constness == hir::Constness::NotConst
51 && feature_allowed(tcx, def_id, sym::const_trait_bound_opt_out)
52 {
53 continue;
54 }
55
56 let generics = tcx.generics_of(current); 41 let generics = tcx.generics_of(current);
57 let def = generics.type_param(p, tcx); 42 let def = generics.type_param(p, tcx);
58 let span = tcx.def_span(def.def_id); 43 let span = tcx.def_span(def.def_id);
@@ -77,18 +62,17 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
77 } 62 }
78 63
79 for local in &body.local_decls { 64 for local in &body.local_decls {
80 check_ty(tcx, local.ty, local.source_info.span, def_id)?; 65 check_ty(tcx, local.ty, local.source_info.span)?;
81 } 66 }
82 // impl trait is gone in MIR, so check the return type manually 67 // impl trait is gone in MIR, so check the return type manually
83 check_ty( 68 check_ty(
84 tcx, 69 tcx,
85 tcx.fn_sig(def_id).output().skip_binder(), 70 tcx.fn_sig(def_id).output().skip_binder(),
86 body.local_decls.iter().next().unwrap().source_info.span, 71 body.local_decls.iter().next().unwrap().source_info.span,
87 def_id,
88 )?; 72 )?;
89 73
90 for bb in body.basic_blocks() { 74 for bb in body.basic_blocks() {
91 check_terminator(tcx, body, def_id, bb.terminator())?; 75 check_terminator(tcx, body, bb.terminator())?;
92 for stmt in &bb.statements { 76 for stmt in &bb.statements {
93 check_statement(tcx, body, def_id, stmt)?; 77 check_statement(tcx, body, def_id, stmt)?;
94 } 78 }
@@ -96,7 +80,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
96 Ok(()) 80 Ok(())
97} 81}
98 82
99fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> McfResult { 83fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
100 for arg in ty.walk() { 84 for arg in ty.walk() {
101 let ty = match arg.unpack() { 85 let ty = match arg.unpack() {
102 GenericArgKind::Type(ty) => ty, 86 GenericArgKind::Type(ty) => ty,
@@ -108,15 +92,11 @@ fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> Mc
108 92
109 match ty.kind() { 93 match ty.kind() {
110 ty::Ref(_, _, hir::Mutability::Mut) => { 94 ty::Ref(_, _, hir::Mutability::Mut) => {
111 if !feature_allowed(tcx, fn_def_id, sym::const_mut_refs) {
112 return Err((span, "mutable references in const fn are unstable".into())); 95 return Err((span, "mutable references in const fn are unstable".into()));
113 }
114 } 96 }
115 ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())), 97 ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
116 ty::FnPtr(..) => { 98 ty::FnPtr(..) => {
117 if !tcx.const_fn_is_allowed_fn_ptr(fn_def_id) {
118 return Err((span, "function pointers in const fn are unstable".into())); 99 return Err((span, "function pointers in const fn are unstable".into()));
119 }
120 } 100 }
121 ty::Dynamic(preds, _) => { 101 ty::Dynamic(preds, _) => {
122 for pred in preds.iter() { 102 for pred in preds.iter() {
@@ -161,12 +141,12 @@ fn check_rvalue(
161 Err((span, "cannot access thread local storage in const fn".into())) 141 Err((span, "cannot access thread local storage in const fn".into()))
162 } 142 }
163 Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => { 143 Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => {
164 check_operand(tcx, operand, span, def_id, body) 144 check_operand(tcx, operand, span, body)
165 } 145 }
166 Rvalue::Len(place) 146 Rvalue::Len(place)
167 | Rvalue::Discriminant(place) 147 | Rvalue::Discriminant(place)
168 | Rvalue::Ref(_, _, place) 148 | Rvalue::Ref(_, _, place)
169 | Rvalue::AddressOf(_, place) => check_place(tcx, *place, span, def_id, body), 149 | Rvalue::AddressOf(_, place) => check_place(tcx, *place, span, body),
170 Rvalue::Cast(CastKind::Misc, operand, cast_ty) => { 150 Rvalue::Cast(CastKind::Misc, operand, cast_ty) => {
171 use rustc_middle::ty::cast::CastTy; 151 use rustc_middle::ty::cast::CastTy;
172 let cast_in = CastTy::from_ty(operand.ty(body, tcx)).expect("bad input type for cast"); 152 let cast_in = CastTy::from_ty(operand.ty(body, tcx)).expect("bad input type for cast");
@@ -175,14 +155,14 @@ fn check_rvalue(
175 (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) => { 155 (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) => {
176 Err((span, "casting pointers to ints is unstable in const fn".into())) 156 Err((span, "casting pointers to ints is unstable in const fn".into()))
177 } 157 }
178 _ => check_operand(tcx, operand, span, def_id, body), 158 _ => check_operand(tcx, operand, span, body),
179 } 159 }
180 } 160 }
181 Rvalue::Cast( 161 Rvalue::Cast(
182 CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer), 162 CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer),
183 operand, 163 operand,
184 _, 164 _,
185 ) => check_operand(tcx, operand, span, def_id, body), 165 ) => check_operand(tcx, operand, span, body),
186 Rvalue::Cast( 166 Rvalue::Cast(
187 CastKind::Pointer( 167 CastKind::Pointer(
188 PointerCast::UnsafeFnPointer 168 PointerCast::UnsafeFnPointer
@@ -204,7 +184,7 @@ fn check_rvalue(
204 }; 184 };
205 let unsized_ty = tcx.struct_tail_erasing_lifetimes(pointee_ty, tcx.param_env(def_id)); 185 let unsized_ty = tcx.struct_tail_erasing_lifetimes(pointee_ty, tcx.param_env(def_id));
206 if let ty::Slice(_) | ty::Str = unsized_ty.kind() { 186 if let ty::Slice(_) | ty::Str = unsized_ty.kind() {
207 check_operand(tcx, op, span, def_id, body)?; 187 check_operand(tcx, op, span, body)?;
208 // Casting/coercing things to slices is fine. 188 // Casting/coercing things to slices is fine.
209 Ok(()) 189 Ok(())
210 } else { 190 } else {
@@ -214,8 +194,8 @@ fn check_rvalue(
214 } 194 }
215 // binops are fine on integers 195 // binops are fine on integers
216 Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => { 196 Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => {
217 check_operand(tcx, lhs, span, def_id, body)?; 197 check_operand(tcx, lhs, span, body)?;
218 check_operand(tcx, rhs, span, def_id, body)?; 198 check_operand(tcx, rhs, span, body)?;
219 let ty = lhs.ty(body, tcx); 199 let ty = lhs.ty(body, tcx);
220 if ty.is_integral() || ty.is_bool() || ty.is_char() { 200 if ty.is_integral() || ty.is_bool() || ty.is_char() {
221 Ok(()) 201 Ok(())
@@ -230,14 +210,14 @@ fn check_rvalue(
230 Rvalue::UnaryOp(_, operand) => { 210 Rvalue::UnaryOp(_, operand) => {
231 let ty = operand.ty(body, tcx); 211 let ty = operand.ty(body, tcx);
232 if ty.is_integral() || ty.is_bool() { 212 if ty.is_integral() || ty.is_bool() {
233 check_operand(tcx, operand, span, def_id, body) 213 check_operand(tcx, operand, span, body)
234 } else { 214 } else {
235 Err((span, "only int and `bool` operations are stable in const fn".into())) 215 Err((span, "only int and `bool` operations are stable in const fn".into()))
236 } 216 }
237 } 217 }
238 Rvalue::Aggregate(_, operands) => { 218 Rvalue::Aggregate(_, operands) => {
239 for operand in operands { 219 for operand in operands {
240 check_operand(tcx, operand, span, def_id, body)?; 220 check_operand(tcx, operand, span, body)?;
241 } 221 }
242 Ok(()) 222 Ok(())
243 } 223 }
@@ -253,15 +233,15 @@ fn check_statement(
253 let span = statement.source_info.span; 233 let span = statement.source_info.span;
254 match &statement.kind { 234 match &statement.kind {
255 StatementKind::Assign(box (place, rval)) => { 235 StatementKind::Assign(box (place, rval)) => {
256 check_place(tcx, *place, span, def_id, body)?; 236 check_place(tcx, *place, span, body)?;
257 check_rvalue(tcx, body, def_id, rval, span) 237 check_rvalue(tcx, body, def_id, rval, span)
258 } 238 }
259 239
260 StatementKind::FakeRead(_, place) => check_place(tcx, **place, span, def_id, body), 240 StatementKind::FakeRead(_, place) => check_place(tcx, **place, span, body),
261 241
262 // just an assignment 242 // just an assignment
263 StatementKind::SetDiscriminant { place, .. } => { 243 StatementKind::SetDiscriminant { place, .. } => {
264 check_place(tcx, **place, span, def_id, body) 244 check_place(tcx, **place, span, body)
265 } 245 }
266 246
267 StatementKind::LlvmInlineAsm { .. } => { 247 StatementKind::LlvmInlineAsm { .. } => {
@@ -282,11 +262,10 @@ fn check_operand(
282 tcx: TyCtxt<'tcx>, 262 tcx: TyCtxt<'tcx>,
283 operand: &Operand<'tcx>, 263 operand: &Operand<'tcx>,
284 span: Span, 264 span: Span,
285 def_id: DefId,
286 body: &Body<'tcx>, 265 body: &Body<'tcx>,
287) -> McfResult { 266) -> McfResult {
288 match operand { 267 match operand {
289 Operand::Move(place) | Operand::Copy(place) => check_place(tcx, *place, span, def_id, body), 268 Operand::Move(place) | Operand::Copy(place) => check_place(tcx, *place, span, body),
290 Operand::Constant(c) => match c.check_static_ptr(tcx) { 269 Operand::Constant(c) => match c.check_static_ptr(tcx) {
291 Some(_) => Err((span, "cannot access `static` items in const fn".into())), 270 Some(_) => Err((span, "cannot access `static` items in const fn".into())),
292 None => Ok(()), 271 None => Ok(()),
@@ -298,7 +277,6 @@ fn check_place(
298 tcx: TyCtxt<'tcx>, 277 tcx: TyCtxt<'tcx>,
299 place: Place<'tcx>, 278 place: Place<'tcx>,
300 span: Span, 279 span: Span,
301 def_id: DefId,
302 body: &Body<'tcx>, 280 body: &Body<'tcx>,
303) -> McfResult { 281) -> McfResult {
304 let mut cursor = place.projection.as_ref(); 282 let mut cursor = place.projection.as_ref();
@@ -310,9 +288,7 @@ fn check_place(
310 if let Some(def) = base_ty.ty_adt_def() { 288 if let Some(def) = base_ty.ty_adt_def() {
311 // No union field accesses in `const fn` 289 // No union field accesses in `const fn`
312 if def.is_union() { 290 if def.is_union() {
313 if !feature_allowed(tcx, def_id, sym::const_fn_union) {
314 return Err((span, "accessing union fields is unstable".into())); 291 return Err((span, "accessing union fields is unstable".into()));
315 }
316 } 292 }
317 } 293 }
318 } 294 }
@@ -327,48 +303,9 @@ fn check_place(
327 Ok(()) 303 Ok(())
328} 304}
329 305
330/// Returns `true` if the given feature gate is allowed within the function with the given `DefId`.
331fn feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool {
332 // All features require that the corresponding gate be enabled,
333 // even if the function has `#[allow_internal_unstable(the_gate)]`.
334 if !tcx.features().enabled(feature_gate) {
335 return false;
336 }
337
338 // If this crate is not using stability attributes, or this function is not claiming to be a
339 // stable `const fn`, that is all that is required.
340 if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) {
341 return true;
342 }
343
344 // However, we cannot allow stable `const fn`s to use unstable features without an explicit
345 // opt-in via `allow_internal_unstable`.
346 super::check_consts::allow_internal_unstable(tcx, def_id, feature_gate)
347}
348
349/// Returns `true` if the given library feature gate is allowed within the function with the given `DefId`.
350pub fn lib_feature_allowed(tcx: TyCtxt<'tcx>, def_id: DefId, feature_gate: Symbol) -> bool {
351 // All features require that the corresponding gate be enabled,
352 // even if the function has `#[allow_internal_unstable(the_gate)]`.
353 if !tcx.features().declared_lib_features.iter().any(|&(sym, _)| sym == feature_gate) {
354 return false;
355 }
356
357 // If this crate is not using stability attributes, or this function is not claiming to be a
358 // stable `const fn`, that is all that is required.
359 if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) {
360 return true;
361 }
362
363 // However, we cannot allow stable `const fn`s to use unstable features without an explicit
364 // opt-in via `allow_internal_unstable`.
365 super::check_consts::allow_internal_unstable(tcx, def_id, feature_gate)
366}
367
368fn check_terminator( 306fn check_terminator(
369 tcx: TyCtxt<'tcx>, 307 tcx: TyCtxt<'tcx>,
370 body: &'a Body<'tcx>, 308 body: &'a Body<'tcx>,
371 def_id: DefId,
372 terminator: &Terminator<'tcx>, 309 terminator: &Terminator<'tcx>,
373) -> McfResult { 310) -> McfResult {
374 let span = terminator.source_info.span; 311 let span = terminator.source_info.span;
@@ -380,14 +317,14 @@ fn check_terminator(
380 | TerminatorKind::Resume 317 | TerminatorKind::Resume
381 | TerminatorKind::Unreachable => Ok(()), 318 | TerminatorKind::Unreachable => Ok(()),
382 319
383 TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, def_id, body), 320 TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, body),
384 TerminatorKind::DropAndReplace { place, value, .. } => { 321 TerminatorKind::DropAndReplace { place, value, .. } => {
385 check_place(tcx, *place, span, def_id, body)?; 322 check_place(tcx, *place, span, body)?;
386 check_operand(tcx, value, span, def_id, body) 323 check_operand(tcx, value, span, body)
387 } 324 }
388 325
389 TerminatorKind::SwitchInt { discr, switch_ty: _, values: _, targets: _ } => { 326 TerminatorKind::SwitchInt { discr, switch_ty: _, values: _, targets: _ } => {
390 check_operand(tcx, discr, span, def_id, body) 327 check_operand(tcx, discr, span, body)
391 } 328 }
392 329
393 TerminatorKind::Abort => Err((span, "abort is not stable in const fn".into())), 330 TerminatorKind::Abort => Err((span, "abort is not stable in const fn".into())),
@@ -405,15 +342,7 @@ fn check_terminator(
405 } => { 342 } => {
406 let fn_ty = func.ty(body, tcx); 343 let fn_ty = func.ty(body, tcx);
407 if let ty::FnDef(fn_def_id, _) = *fn_ty.kind() { 344 if let ty::FnDef(fn_def_id, _) = *fn_ty.kind() {
408 // Allow unstable const if we opt in by using #[allow_internal_unstable] 345 if !rustc_mir::const_eval::is_min_const_fn(tcx, fn_def_id)
409 // on function or macro declaration.
410 if !crate::const_eval::is_min_const_fn(tcx, fn_def_id)
411 && !crate::const_eval::is_unstable_const_fn(tcx, fn_def_id)
412 .map(|feature| {
413 span.allows_unstable(feature)
414 || lib_feature_allowed(tcx, def_id, feature)
415 })
416 .unwrap_or(false)
417 { 346 {
418 return Err(( 347 return Err((
419 span, 348 span,
@@ -432,7 +361,6 @@ fn check_terminator(
432 // transmutes in const fn before we add more hacks to this. 361 // transmutes in const fn before we add more hacks to this.
433 if tcx.fn_sig(fn_def_id).abi() == RustIntrinsic 362 if tcx.fn_sig(fn_def_id).abi() == RustIntrinsic
434 && tcx.item_name(fn_def_id) == sym::transmute 363 && tcx.item_name(fn_def_id) == sym::transmute
435 && !feature_allowed(tcx, def_id, sym::const_fn_transmute)
436 { 364 {
437 return Err(( 365 return Err((
438 span, 366 span,
@@ -440,10 +368,10 @@ fn check_terminator(
440 )); 368 ));
441 } 369 }
442 370
443 check_operand(tcx, func, span, fn_def_id, body)?; 371 check_operand(tcx, func, span, body)?;
444 372
445 for arg in args { 373 for arg in args {
446 check_operand(tcx, arg, span, fn_def_id, body)?; 374 check_operand(tcx, arg, span, body)?;
447 } 375 }
448 Ok(()) 376 Ok(())
449 } else { 377 } else {
@@ -452,7 +380,7 @@ fn check_terminator(
452 } 380 }
453 381
454 TerminatorKind::Assert { cond, expected: _, msg: _, target: _, cleanup: _ } => { 382 TerminatorKind::Assert { cond, expected: _, msg: _, target: _, cleanup: _ } => {
455 check_operand(tcx, cond, span, def_id, body) 383 check_operand(tcx, cond, span, body)
456 } 384 }
457 385
458 TerminatorKind::InlineAsm { .. } => { 386 TerminatorKind::InlineAsm { .. } => {