From 9755fe80ee88803f2ecf7e86d7ae6d6fb8e25f55 Mon Sep 17 00:00:00 2001 From: Ali Raheem Date: Wed, 7 Aug 2019 15:59:18 +0100 Subject: [PATCH 001/413] Add fs::read_dir() and ReadDir warning about iterator order + example --- src/libstd/fs.rs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index f7c32a5c20d3d..2a55c79a93ce4 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -114,6 +114,11 @@ pub struct Metadata(fs_imp::FileAttr); /// information like the entry's path and possibly other metadata can be /// learned. /// +/// #### Note: Iteration Order is Implementation-Defined +/// +/// The order in which this iterator returns entries is platform and filesystem +/// dependent. +/// /// # Errors /// /// This [`io::Result`] will be an [`Err`] if there's some sort of intermittent @@ -1959,6 +1964,11 @@ pub fn remove_dir_all>(path: P) -> io::Result<()> { /// /// [changes]: ../io/index.html#platform-specific-behavior /// +/// #### Note: Iteration Order is Implementation-Defined +/// +/// The order in which this iterator returns entries is platform and filesystem +/// dependent. +/// /// # Errors /// /// This function will return an error in the following situations, but is not @@ -1991,6 +2001,28 @@ pub fn remove_dir_all>(path: P) -> io::Result<()> { /// Ok(()) /// } /// ``` +/// +/// ```rust,no_run +/// use std::{fs, io}; +/// +/// fn main() -> io::Result<()> { +/// // The order read_dir returns entries is not guaranteed. If reproducible +/// // ordering is required the entries should be explicitly sorted. +/// let mut entries = fs::read_dir(".")? +/// .map(|res| res.map(|e| e.path())) +/// .collect::, io::Error>>()?; +/// +/// println!( +/// "Entries before sorting (may or may not be sorted already): {:?}", +/// entries +/// ); +/// +/// entries.sort(); +/// +/// println!("Entries after sorting: {:?}", entries); +/// Ok(()) +/// } +/// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn read_dir>(path: P) -> io::Result { fs_imp::readdir(path.as_ref()).map(ReadDir) From 8068812d042fa1bfb2133332152ee591705fdef7 Mon Sep 17 00:00:00 2001 From: Ali Raheem Date: Thu, 8 Aug 2019 15:33:39 +0100 Subject: [PATCH 002/413] Remove Iteration order heading --- src/libstd/fs.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 2a55c79a93ce4..ad279d7f754a6 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -114,8 +114,6 @@ pub struct Metadata(fs_imp::FileAttr); /// information like the entry's path and possibly other metadata can be /// learned. /// -/// #### Note: Iteration Order is Implementation-Defined -/// /// The order in which this iterator returns entries is platform and filesystem /// dependent. /// @@ -1964,8 +1962,6 @@ pub fn remove_dir_all>(path: P) -> io::Result<()> { /// /// [changes]: ../io/index.html#platform-specific-behavior /// -/// #### Note: Iteration Order is Implementation-Defined -/// /// The order in which this iterator returns entries is platform and filesystem /// dependent. /// From 53c504650dc6e51c45a256f56c92b872082d0642 Mon Sep 17 00:00:00 2001 From: Ali Raheem Date: Thu, 15 Aug 2019 10:53:29 +0100 Subject: [PATCH 003/413] Fix gramitcal error in read_dir example --- src/libstd/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index ad279d7f754a6..42ce044c5abe5 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -2002,7 +2002,7 @@ pub fn remove_dir_all>(path: P) -> io::Result<()> { /// use std::{fs, io}; /// /// fn main() -> io::Result<()> { -/// // The order read_dir returns entries is not guaranteed. If reproducible +/// // The order in which `read_dir` returns entries is not guaranteed. If reproducible /// // ordering is required the entries should be explicitly sorted. /// let mut entries = fs::read_dir(".")? /// .map(|res| res.map(|e| e.path())) From 9a6ca413714271adac017cbdd764a7de8b244001 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Wed, 10 Jul 2019 12:22:07 +0200 Subject: [PATCH 004/413] HirIdify hir::Crate.modules --- src/librustc/hir/lowering.rs | 6 +++--- src/librustc/hir/lowering/item.rs | 6 ++++-- src/librustc/hir/map/hir_id_validator.rs | 2 +- src/librustc/hir/map/mod.rs | 4 +--- src/librustc/hir/mod.rs | 2 +- src/librustc/lint/context.rs | 2 +- src/librustc_interface/passes.rs | 15 ++++++++------- src/librustc_typeck/impl_wf_check.rs | 2 +- src/librustc_typeck/lib.rs | 4 ++-- 9 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 7ec3210613727..4a254d2123ecd 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -97,7 +97,7 @@ pub struct LoweringContext<'a> { trait_impls: BTreeMap>, - modules: BTreeMap, + modules: BTreeMap, generator_kind: Option, @@ -141,7 +141,7 @@ pub struct LoweringContext<'a> { /// vector. in_scope_lifetimes: Vec, - current_module: NodeId, + current_module: hir::HirId, type_def_lifetime_params: DefIdMap, @@ -262,7 +262,7 @@ pub fn lower_crate( is_in_dyn_type: false, anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough, type_def_lifetime_params: Default::default(), - current_module: CRATE_NODE_ID, + current_module: hir::CRATE_HIR_ID, current_hir_id_owner: vec![(CRATE_DEF_INDEX, 0)], item_local_id_counters: Default::default(), node_id_to_hir_id: IndexVec::new(), diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 4f9a9ed5673c7..780dd79435bf2 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -45,14 +45,16 @@ impl<'tcx, 'interner> ItemLowerer<'tcx, 'interner> { impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> { fn visit_mod(&mut self, m: &'tcx Mod, _s: Span, _attrs: &[Attribute], n: NodeId) { - self.lctx.modules.insert(n, hir::ModuleItems { + let hir_id = self.lctx.lower_node_id(n); + + self.lctx.modules.insert(hir_id, hir::ModuleItems { items: BTreeSet::new(), trait_items: BTreeSet::new(), impl_items: BTreeSet::new(), }); let old = self.lctx.current_module; - self.lctx.current_module = n; + self.lctx.current_module = hir_id; visit::walk_mod(self, m); self.lctx.current_module = old; } diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index 889659382d060..b66c2ce1178a4 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -10,7 +10,7 @@ pub fn check_crate(hir_map: &hir::map::Map<'_>) { let errors = Lock::new(Vec::new()); par_iter(&hir_map.krate().modules).for_each(|(module_id, _)| { - let local_def_id = hir_map.local_def_id_from_node_id(*module_id); + let local_def_id = hir_map.local_def_id(*module_id); hir_map.visit_item_likes_in_module(local_def_id, &mut OuterVisitor { hir_map, errors: &errors, diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index f80e527dfd9b7..e833c2bb8f3d8 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -539,9 +539,7 @@ impl<'hir> Map<'hir> { // in the expect_* calls the loops below self.read(hir_id); - let node_id = self.hir_to_node_id[&hir_id]; - - let module = &self.forest.krate.modules[&node_id]; + let module = &self.forest.krate.modules[&hir_id]; for id in &module.items { visitor.visit_item(self.expect_item(*id)); diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 983048188527f..d639fdf6abc2c 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -767,7 +767,7 @@ pub struct Crate { /// A list of modules written out in the order in which they /// appear in the crate. This includes the main crate module. - pub modules: BTreeMap, + pub modules: BTreeMap, } impl Crate { diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 6801fa8d8dbe5..a44dbff27ed6e 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -1515,7 +1515,7 @@ pub fn check_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>( time(tcx.sess, "module lints", || { // Run per-module lints par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { - tcx.ensure().lint_mod(tcx.hir().local_def_id_from_node_id(module)); + tcx.ensure().lint_mod(tcx.hir().local_def_id(module)); }); }); }); diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 8b0b5a5b7a2bd..68e799eced2f3 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -913,10 +913,10 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { }); }, { par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { - tcx.ensure().check_mod_loops(tcx.hir().local_def_id_from_node_id(module)); - tcx.ensure().check_mod_attrs(tcx.hir().local_def_id_from_node_id(module)); - tcx.ensure().check_mod_unstable_api_usage( - tcx.hir().local_def_id_from_node_id(module)); + let local_def_id = tcx.hir().local_def_id(module); + tcx.ensure().check_mod_loops(local_def_id); + tcx.ensure().check_mod_attrs(local_def_id); + tcx.ensure().check_mod_unstable_api_usage(local_def_id); }); }); }); @@ -939,9 +939,10 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { // "not all control paths return a value" is reported here. // // maybe move the check to a MIR pass? - tcx.ensure().check_mod_liveness(tcx.hir().local_def_id_from_node_id(module)); + let local_def_id = tcx.hir().local_def_id(module); - tcx.ensure().check_mod_intrinsics(tcx.hir().local_def_id_from_node_id(module)); + tcx.ensure().check_mod_liveness(local_def_id); + tcx.ensure().check_mod_intrinsics(local_def_id); }); }); }); @@ -1001,7 +1002,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { }, { time(sess, "privacy checking modules", || { par_iter(&tcx.hir().krate().modules).for_each(|(&module, _)| { - tcx.ensure().check_mod_privacy(tcx.hir().local_def_id_from_node_id(module)); + tcx.ensure().check_mod_privacy(tcx.hir().local_def_id(module)); }); }); }); diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index fcfd9adef54df..e3302f299ea71 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -54,7 +54,7 @@ pub fn impl_wf_check(tcx: TyCtxt<'_>) { // but it's one that we must perform earlier than the rest of // WfCheck. for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().check_mod_impl_wf(tcx.hir().local_def_id_from_node_id(module)); + tcx.ensure().check_mod_impl_wf(tcx.hir().local_def_id(module)); } } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 9d9a9d9b559e4..53506454be79e 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -306,7 +306,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { tcx.sess.track_errors(|| { time(tcx.sess, "type collecting", || { for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id_from_node_id(module)); + tcx.ensure().collect_mod_item_types(tcx.hir().local_def_id(module)); } }); })?; @@ -341,7 +341,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorReported> { time(tcx.sess, "item-types checking", || { for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().check_mod_item_types(tcx.hir().local_def_id_from_node_id(module)); + tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module)); } }); From 3c820fef9fafca1f25da37274aea683b9e341339 Mon Sep 17 00:00:00 2001 From: Ali Raheem Date: Mon, 26 Aug 2019 11:24:08 +0100 Subject: [PATCH 005/413] Comment out println in read_dir sorting example --- src/libstd/fs.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 42ce044c5abe5..689c50c6b80fa 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -2008,14 +2008,14 @@ pub fn remove_dir_all>(path: P) -> io::Result<()> { /// .map(|res| res.map(|e| e.path())) /// .collect::, io::Error>>()?; /// -/// println!( -/// "Entries before sorting (may or may not be sorted already): {:?}", -/// entries -/// ); +/// // println!( +/// // "Entries before sorting (may or may not be sorted already): {:?}", +/// // entries +/// // ); /// /// entries.sort(); /// -/// println!("Entries after sorting: {:?}", entries); +/// // println!("Entries after sorting: {:?}", entries); /// Ok(()) /// } /// ``` From c015927af3604ec5305e078c1a57c81901f81190 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Tue, 27 Aug 2019 00:20:21 -0400 Subject: [PATCH 006/413] Fix ICE in rustdoc when merging generic and where bounds in the case of an Fn with an output Fixes #57180 --- src/librustdoc/clean/simplify.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 8758ab1969116..2142d6de5da5d 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -122,9 +122,9 @@ pub fn merge_bounds( }, }); } - PP::Parenthesized { ref mut output, .. } => { - assert!(output.is_none()); - if *rhs != clean::Type::Tuple(Vec::new()) { + PP::Parenthesized { ref mut output, .. } => match output { + Some(o) => assert!(o == rhs), + None => if *rhs != clean::Type::Tuple(Vec::new()) { *output = Some(rhs.clone()); } } From 09f6b44790afa924aabf723518931191d92eb472 Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Tue, 27 Aug 2019 00:22:31 -0400 Subject: [PATCH 007/413] Simplify some code in rustdoc's simplify --- src/librustdoc/clean/simplify.rs | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 2142d6de5da5d..73bc0386326ce 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -35,7 +35,7 @@ pub fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> Vec { match ty { clean::Generic(s) => params.entry(s).or_default() .extend(bounds), - t => tybounds.push((t, ty_bounds(bounds))), + t => tybounds.push((t, bounds)), } } WP::RegionPredicate { lifetime, bounds } => { @@ -45,11 +45,6 @@ pub fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> Vec { } } - // Simplify the type parameter bounds on all the generics - let mut params = params.into_iter().map(|(k, v)| { - (k, ty_bounds(v)) - }).collect::>(); - // Look for equality predicates on associated types that can be merged into // general bound predicates equalities.retain(|&(ref lhs, ref rhs)| { @@ -73,7 +68,7 @@ pub fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> Vec { // And finally, let's reassemble everything let mut clauses = Vec::new(); clauses.extend(lifetimes.into_iter().map(|(lt, bounds)| { - WP::RegionPredicate { lifetime: lt, bounds: bounds } + WP::RegionPredicate { lifetime: lt, bounds } })); clauses.extend(params.into_iter().map(|(k, v)| { WP::BoundPredicate { @@ -82,10 +77,10 @@ pub fn where_clauses(cx: &DocContext<'_>, clauses: Vec) -> Vec { } })); clauses.extend(tybounds.into_iter().map(|(ty, bounds)| { - WP::BoundPredicate { ty: ty, bounds: bounds } + WP::BoundPredicate { ty, bounds } })); clauses.extend(equalities.into_iter().map(|(lhs, rhs)| { - WP::EqPredicate { lhs: lhs, rhs: rhs } + WP::EqPredicate { lhs, rhs } })); clauses } @@ -137,7 +132,7 @@ pub fn ty_params(mut params: Vec) -> Vec { - *bounds = ty_bounds(mem::take(bounds)); + *bounds = mem::take(bounds); } _ => panic!("expected only type parameters"), } @@ -145,10 +140,6 @@ pub fn ty_params(mut params: Vec) -> Vec) -> Vec { - bounds -} - fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, trait_: DefId) -> bool { if child == trait_ { From 143b83a3c1e3a03d9795b891e4f2298c5e59f66a Mon Sep 17 00:00:00 2001 From: Paul Daniel Faria Date: Wed, 28 Aug 2019 00:21:30 -0400 Subject: [PATCH 008/413] Add regression test for issue, apply suggestion to convert to assert_eq --- src/librustdoc/clean/simplify.rs | 2 +- src/test/rustdoc/auxiliary/issue-57180.rs | 16 ++++++++++++++++ src/test/rustdoc/issue-57180.rs | 7 +++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/test/rustdoc/auxiliary/issue-57180.rs create mode 100644 src/test/rustdoc/issue-57180.rs diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 73bc0386326ce..853170542e083 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -118,7 +118,7 @@ pub fn merge_bounds( }); } PP::Parenthesized { ref mut output, .. } => match output { - Some(o) => assert!(o == rhs), + Some(o) => assert_eq!(o, rhs), None => if *rhs != clean::Type::Tuple(Vec::new()) { *output = Some(rhs.clone()); } diff --git a/src/test/rustdoc/auxiliary/issue-57180.rs b/src/test/rustdoc/auxiliary/issue-57180.rs new file mode 100644 index 0000000000000..4e2f4b87c020e --- /dev/null +++ b/src/test/rustdoc/auxiliary/issue-57180.rs @@ -0,0 +1,16 @@ +// compile-flags: -Cmetadata=aux + +pub trait Trait { +} + +pub struct Struct +{ + _p: ::std::marker::PhantomData, +} + +impl u32> +Trait for Struct + where + F: Fn() -> u32, +{ +} diff --git a/src/test/rustdoc/issue-57180.rs b/src/test/rustdoc/issue-57180.rs new file mode 100644 index 0000000000000..14bd2b0fec0d5 --- /dev/null +++ b/src/test/rustdoc/issue-57180.rs @@ -0,0 +1,7 @@ +// aux-build:issue-57180.rs + +extern crate issue_57180; +use issue_57180::Trait; + +fn main() { +} From d61605cef866008a19e33eb596df1d76ff1571f3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2019 09:03:58 +1000 Subject: [PATCH 009/413] Don't call `self.parse()` in `Compiler::crate_name()` unless necessary. --- src/librustc_interface/queries.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index ed50dadb60099..996e9fae0db56 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -126,17 +126,18 @@ impl Compiler { pub fn crate_name(&self) -> Result<&Query> { self.queries.crate_name.compute(|| { - let parse_result = self.parse()?; - let krate = parse_result.peek(); - let result = match self.crate_name { + Ok(match self.crate_name { Some(ref crate_name) => crate_name.clone(), - None => rustc_codegen_utils::link::find_crate_name( - Some(self.session()), - &krate.attrs, - &self.input - ), - }; - Ok(result) + None => { + let parse_result = self.parse()?; + let krate = parse_result.peek(); + rustc_codegen_utils::link::find_crate_name( + Some(self.session()), + &krate.attrs, + &self.input + ) + } + }) }) } From cd0c21b0e5b68e29c63c3c98db9147cb0e5a3bc8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2019 16:24:01 +1000 Subject: [PATCH 010/413] Remove `lower_to_hir()` call from `prepare_output()`. It's a false dependency. The result isn't used and there are no relevant side-effects. --- src/librustc_interface/queries.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 996e9fae0db56..c281bc5360704 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -195,7 +195,6 @@ impl Compiler { pub fn prepare_outputs(&self) -> Result<&Query> { self.queries.prepare_outputs.compute(|| { - self.lower_to_hir()?; let krate = self.expansion()?; let krate = krate.peek(); let crate_name = self.crate_name()?; From 91fd8efd265b60a635aff89d1c2d0a8aea45fdf9 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Mon, 9 Sep 2019 08:02:26 +1000 Subject: [PATCH 011/413] document the unstable iter_order_by library feature --- src/doc/unstable-book/src/iter-order-by.md | 9 +++++++++ src/libcore/iter/traits/iterator.rs | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 src/doc/unstable-book/src/iter-order-by.md diff --git a/src/doc/unstable-book/src/iter-order-by.md b/src/doc/unstable-book/src/iter-order-by.md new file mode 100644 index 0000000000000..1ed97872c881c --- /dev/null +++ b/src/doc/unstable-book/src/iter-order-by.md @@ -0,0 +1,9 @@ +# `iter_order_by` + +The tracking issue for this feature is: [#64295] + +[#64295]: https://github.com/rust-lang/rust/issues/64295 + +------------------------ + +Add `cmp_by`, `partial_cmp_by` and `eq_by` methods to `Iterator` in the same vein as `max_by` and `min_by`. diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index c09df3f7f22cb..266f1e6a78102 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -2585,7 +2585,7 @@ pub trait Iterator { /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (x * x).cmp(&y)), Ordering::Equal); /// assert_eq!(xs.iter().cmp_by(&ys, |&x, &y| (2 * x).cmp(&y)), Ordering::Greater); /// ``` - #[unstable(feature = "iter_order_by", issue = "0")] + #[unstable(feature = "iter_order_by", issue = "64295")] fn cmp_by(mut self, other: I, mut cmp: F) -> Ordering where Self: Sized, @@ -2668,7 +2668,7 @@ pub trait Iterator { /// Some(Ordering::Greater) /// ); /// ``` - #[unstable(feature = "iter_order_by", issue = "0")] + #[unstable(feature = "iter_order_by", issue = "64295")] fn partial_cmp_by(mut self, other: I, mut partial_cmp: F) -> Option where Self: Sized, @@ -2733,7 +2733,7 @@ pub trait Iterator { /// /// assert!(xs.iter().eq_by(&ys, |&x, &y| x * x == y)); /// ``` - #[unstable(feature = "iter_order_by", issue = "0")] + #[unstable(feature = "iter_order_by", issue = "64295")] fn eq_by(mut self, other: I, mut eq: F) -> bool where Self: Sized, From 1161aeb2b423da744e687315648a49cc4774220b Mon Sep 17 00:00:00 2001 From: Ali Raheem Date: Mon, 9 Sep 2019 20:38:21 +0100 Subject: [PATCH 012/413] Replace println statements with explanatory comments --- src/libstd/fs.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 689c50c6b80fa..246587b4233cd 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -2002,20 +2002,17 @@ pub fn remove_dir_all>(path: P) -> io::Result<()> { /// use std::{fs, io}; /// /// fn main() -> io::Result<()> { -/// // The order in which `read_dir` returns entries is not guaranteed. If reproducible -/// // ordering is required the entries should be explicitly sorted. /// let mut entries = fs::read_dir(".")? /// .map(|res| res.map(|e| e.path())) /// .collect::, io::Error>>()?; /// -/// // println!( -/// // "Entries before sorting (may or may not be sorted already): {:?}", -/// // entries -/// // ); +/// // The order in which `read_dir` returns entries is not guaranteed. If reproducible +/// // ordering is required the entries should be explicitly sorted. /// /// entries.sort(); /// -/// // println!("Entries after sorting: {:?}", entries); +/// // The entries have now been sorted by their path. +/// /// Ok(()) /// } /// ``` From d264a56068d7fd881b2e082c4d80d81d22c4ce79 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2019 16:53:34 +1000 Subject: [PATCH 013/413] Move call site of `dep_graph_future()`. `Compiler::register_plugins()` calls `passes::register_plugins()`, which calls `Compiler::dep_graph_future()`. This is the only way in which a `passes` function calls a `Compiler` function. This commit moves the `dep_graph_future()` call out of `passes::register_plugins()` and into `Compiler::register_plugins()`, which is a more sensible spot for it. This will delay the loading of the dep graph slightly -- from the middle of plugin registration to the end of plugin registration -- but plugin registration is fast enough (especially compared to expansion) that the impact should be neglible. --- src/librustc_interface/passes.rs | 4 ---- src/librustc_interface/queries.rs | 14 +++++++++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 24b44964e4fd2..200da05c57561 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -223,7 +223,6 @@ pub struct PluginInfo { } pub fn register_plugins<'a>( - compiler: &Compiler, sess: &'a Session, cstore: &'a CStore, mut krate: ast::Crate, @@ -261,9 +260,6 @@ pub fn register_plugins<'a>( }); } - // If necessary, compute the dependency graph (in the background). - compiler.dep_graph_future().ok(); - time(sess, "recursion limit", || { middle::recursion_limit::update_limits(sess, &krate); }); diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index c281bc5360704..e056d3feb66ec 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -114,13 +114,21 @@ impl Compiler { let crate_name = self.crate_name()?.peek().clone(); let krate = self.parse()?.take(); - passes::register_plugins( - self, + let result = passes::register_plugins( self.session(), self.cstore(), krate, &crate_name, - ) + ); + + // Compute the dependency graph (in the background). We want to do + // this as early as possible, to give the DepGraph maximum time to + // load before dep_graph() is called, but it also can't happen + // until after rustc_incremental::prepare_session_directory() is + // called, which happens within passes::register_plugins(). + self.dep_graph_future().ok(); + + result }) } From 562903a0a684860c0e51971ea11f1ce97795d6a2 Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Fri, 13 Sep 2019 10:20:17 +0200 Subject: [PATCH 014/413] use `sign` variable in abs and wrapping_abs methods This also makes the code easier to understand by hinting at the significance of `self >> ($BITS - 1)` and by including an explanation in the comments. Also, now overflowing_abs simply uses wrapping_abs, which is clearer and avoids a potential performance regression in the LLVM IR. --- src/libcore/num/mod.rs | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index df1c00ccd184f..9860928427754 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1402,7 +1402,16 @@ $EndFeature, " #[stable(feature = "no_panic_abs", since = "1.13.0")] #[inline] pub const fn wrapping_abs(self) -> Self { - (self ^ (self >> ($BITS - 1))).wrapping_sub(self >> ($BITS - 1)) + // sign is -1 (all ones) for negative numbers, 0 otherwise. + let sign = self >> ($BITS - 1); + // For positive self, sign == 0 so the expression is simply + // (self ^ 0).wrapping_sub(0) == self == abs(self). + // + // For negative self, self ^ sign == self ^ all_ones. + // But all_ones ^ self == all_ones - self == -1 - self. + // So for negative numbers, (self ^ sign).wrapping_sub(sign) is + // (-1 - self).wrapping_sub(-1) == -self == abs(self). + (self ^ sign).wrapping_sub(sign) } } @@ -1761,7 +1770,7 @@ $EndFeature, " #[stable(feature = "no_panic_abs", since = "1.13.0")] #[inline] pub const fn overflowing_abs(self) -> (Self, bool) { - (self ^ (self >> ($BITS - 1))).overflowing_sub(self >> ($BITS - 1)) + (self.wrapping_abs(), self == Self::min_value()) } } @@ -1969,7 +1978,21 @@ $EndFeature, " // Note that the #[inline] above means that the overflow // semantics of the subtraction depend on the crate we're being // inlined into. - (self ^ (self >> ($BITS - 1))) - (self >> ($BITS - 1)) + + // sign is -1 (all ones) for negative numbers, 0 otherwise. + let sign = self >> ($BITS - 1); + // For positive self, sign == 0 so the expression is simply + // (self ^ 0) - 0 == self == abs(self). + // + // For negative self, self ^ sign == self ^ all_ones. + // But all_ones ^ self == all_ones - self == -1 - self. + // So for negative numbers, (self ^ sign) - sign is + // (-1 - self) - -1 == -self == abs(self). + // + // The subtraction overflows when self is min_value(), because + // (-1 - min_value()) - -1 is max_value() - -1 which overflows. + // This is exactly when we want self.abs() to overflow. + (self ^ sign) - sign } } From 612ef5f518198448c43959a6416b9da2964f9167 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 12 Sep 2019 17:04:32 -0400 Subject: [PATCH 015/413] add new tests for re_rebalance_coherence --- ...]-foreign[foreign[t],local]-for-foreign.rs | 14 +++++++++++++ ...pl[t]-foreign[local]-for-fundamental[t].rs | 21 +++++++++++++++++++ .../coherence/impl[t]-foreign[local]-for-t.rs | 16 ++++++++++++++ .../impl[t]-foreign[local]-for-t.stderr | 11 ++++++++++ .../coherence/re-rebalance-coherence-rpass.rs | 14 ------------- 5 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr delete mode 100644 src/test/ui/coherence/re-rebalance-coherence-rpass.rs diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs new file mode 100644 index 0000000000000..61f2637c0c297 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs @@ -0,0 +1,14 @@ +#![feature(re_rebalance_coherence)] + +// run-pass +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; +impl Remote2, Local> for usize { } + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs new file mode 100644 index 0000000000000..586b8de9e95c9 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs @@ -0,0 +1,21 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// run-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Box { + // FIXME(#64412) -- this is expected to error +} + +impl Remote1 for &T { + // FIXME(#64412) -- this is expected to error +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs new file mode 100644 index 0000000000000..6f35c6c9dbc88 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs @@ -0,0 +1,16 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr new file mode 100644 index 0000000000000..be7de8cccb467 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr @@ -0,0 +1,11 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[local]-for-t.rs:12:1 + | +LL | impl Remote1 for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/re-rebalance-coherence-rpass.rs b/src/test/ui/coherence/re-rebalance-coherence-rpass.rs deleted file mode 100644 index bacd3b89fad29..0000000000000 --- a/src/test/ui/coherence/re-rebalance-coherence-rpass.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![allow(dead_code)] -#![feature(re_rebalance_coherence)] - -// run-pass -// aux-build:re_rebalance_coherence_lib.rs - -extern crate re_rebalance_coherence_lib as lib; -use lib::*; - -struct Oracle; -impl Backend for Oracle {} -impl<'a, T:'a, Tab> QueryFragment for BatchInsert<'a, T, Tab> {} - -fn main() {} From e69d1b67b6603e0635c553eff693a0606d282d75 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 13 Sep 2019 14:57:06 -0400 Subject: [PATCH 016/413] change to check-pass --- .../coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs | 2 +- .../ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs index 61f2637c0c297..54d4bf04a583c 100644 --- a/src/test/ui/coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs +++ b/src/test/ui/coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs @@ -1,6 +1,6 @@ #![feature(re_rebalance_coherence)] -// run-pass +// check-pass // compile-flags:--crate-name=test // aux-build:coherence_lib.rs diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs index 586b8de9e95c9..db671cb9bcaba 100644 --- a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs @@ -2,7 +2,7 @@ // compile-flags:--crate-name=test // aux-build:coherence_lib.rs -// run-pass +// check-pass extern crate coherence_lib as lib; use lib::*; From 04b27efa00799f984b7ebc50d37a2d571db9235f Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Thu, 12 Sep 2019 19:59:14 -0400 Subject: [PATCH 017/413] Move to print functions on types instead of impl fmt::Display This will eventually allow us to easily pass in more parameters to the functions without TLS or other such hacks --- src/librustdoc/clean/mod.rs | 14 +- src/librustdoc/html/format.rs | 881 ++++++++++-------- src/librustdoc/html/item_type.rs | 39 +- src/librustdoc/html/render.rs | 127 +-- .../passes/calculate_doc_coverage.rs | 7 +- .../passes/collect_intra_doc_links.rs | 2 +- src/librustdoc/passes/mod.rs | 4 +- src/librustdoc/passes/strip_hidden.rs | 2 +- 8 files changed, 553 insertions(+), 523 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ae70fdc530be6..10c4231b82eeb 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1849,7 +1849,7 @@ fn get_real_types( cx: &DocContext<'_>, recurse: i32, ) -> FxHashSet { - let arg_s = arg.to_string(); + let arg_s = arg.print().to_string(); let mut res = FxHashSet::default(); if recurse >= 10 { // FIXME: remove this whole recurse thing when the recursion bug is fixed return res; @@ -3573,16 +3573,6 @@ pub enum GenericArg { Const(Constant), } -impl fmt::Display for GenericArg { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - GenericArg::Lifetime(lt) => lt.fmt(f), - GenericArg::Type(ty) => ty.fmt(f), - GenericArg::Const(ct) => ct.fmt(f), - } - } -} - #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub enum GenericArgs { AngleBracketed { @@ -4274,7 +4264,7 @@ fn resolve_type(cx: &DocContext<'_>, return Generic(kw::SelfUpper.to_string()); } Res::Def(DefKind::TyParam, _) if path.segments.len() == 1 => { - return Generic(format!("{:#}", path)); + return Generic(format!("{:#}", path.print())); } Res::SelfTy(..) | Res::Def(DefKind::TyParam, _) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index dcd32192ff384..9baa69d981b52 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -99,10 +99,6 @@ impl Buffer { self.into_inner() } - crate fn with_formatter) -> fmt::Result>(&mut self, t: T) { - self.from_display(display_fn(move |f| (t)(f))); - } - crate fn from_display(&mut self, t: T) { if self.for_html { write!(self, "{}", t); @@ -131,8 +127,6 @@ pub struct AsyncSpace(pub hir::IsAsync); /// Similar to VisSpace, but used for mutability #[derive(Copy, Clone)] pub struct MutableSpace(pub clean::Mutability); -/// Wrapper struct for emitting type parameter bounds. -pub struct GenericBounds<'a>(pub &'a [clean::GenericBound]); pub struct AbiSpace(pub Abi); pub struct DefaultSpace(pub bool); @@ -161,102 +155,89 @@ pub struct WhereClause<'a>{ pub end_newline: bool, } -impl<'a> VisSpace<'a> { - pub fn get(self) -> &'a Option { - let VisSpace(v) = self; v - } -} - -impl UnsafetySpace { - pub fn get(&self) -> hir::Unsafety { - let UnsafetySpace(v) = *self; v - } -} - -impl ConstnessSpace { - pub fn get(&self) -> hir::Constness { - let ConstnessSpace(v) = *self; v - } -} - -fn comma_sep(items: &[T]) -> impl fmt::Display + '_ { +fn comma_sep(items: impl Iterator) -> impl fmt::Display { display_fn(move |f| { - for (i, item) in items.iter().enumerate() { + for (i, item) in items.enumerate() { if i != 0 { write!(f, ", ")?; } - fmt::Display::fmt(item, f)?; + fmt::Display::fmt(&item, f)?; } Ok(()) }) } -impl<'a> fmt::Display for GenericBounds<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +crate fn print_generic_bounds(bounds: &[clean::GenericBound]) -> impl fmt::Display + '_ { + display_fn(move |f| { let mut bounds_dup = FxHashSet::default(); - let &GenericBounds(bounds) = self; - for (i, bound) in bounds.iter().filter(|b| bounds_dup.insert(b.to_string())).enumerate() { + for (i, bound) in bounds.iter().filter(|b| { + bounds_dup.insert(b.print().to_string()) + }).enumerate() { if i > 0 { f.write_str(" + ")?; } - fmt::Display::fmt(bound, f)?; + fmt::Display::fmt(&bound.print(), f)?; } Ok(()) - } + }) } -impl fmt::Display for clean::GenericParamDef { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.kind { - clean::GenericParamDefKind::Lifetime => write!(f, "{}", self.name), - clean::GenericParamDefKind::Type { ref bounds, ref default, .. } => { - f.write_str(&self.name)?; +impl clean::GenericParamDef { + crate fn print(&self) -> impl fmt::Display + '_ { + display_fn(move |f| { + match self.kind { + clean::GenericParamDefKind::Lifetime => write!(f, "{}", self.name), + clean::GenericParamDefKind::Type { ref bounds, ref default, .. } => { + f.write_str(&self.name)?; - if !bounds.is_empty() { - if f.alternate() { - write!(f, ": {:#}", GenericBounds(bounds))?; - } else { - write!(f, ": {}", GenericBounds(bounds))?; + if !bounds.is_empty() { + if f.alternate() { + write!(f, ": {:#}", print_generic_bounds(bounds))?; + } else { + write!(f, ": {}", print_generic_bounds(bounds))?; + } + } + + if let Some(ref ty) = default { + if f.alternate() { + write!(f, " = {:#}", ty.print())?; + } else { + write!(f, " = {}", ty.print())?; + } } + + Ok(()) } + clean::GenericParamDefKind::Const { ref ty, .. } => { + f.write_str("const ")?; + f.write_str(&self.name)?; - if let Some(ref ty) = default { if f.alternate() { - write!(f, " = {:#}", ty)?; + write!(f, ": {:#}", ty.print()) } else { - write!(f, " = {}", ty)?; + write!(f, ": {}", ty.print()) } } - - Ok(()) - } - clean::GenericParamDefKind::Const { ref ty, .. } => { - f.write_str("const ")?; - f.write_str(&self.name)?; - - if f.alternate() { - write!(f, ": {:#}", ty) - } else { - write!(f, ": {}", ty) - } } - } + }) } } -impl fmt::Display for clean::Generics { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let real_params = self.params - .iter() - .filter(|p| !p.is_synthetic_type_param()) - .collect::>(); - if real_params.is_empty() { - return Ok(()); - } - if f.alternate() { - write!(f, "<{:#}>", comma_sep(&real_params)) - } else { - write!(f, "<{}>", comma_sep(&real_params)) - } +impl clean::Generics { + crate fn print(&self) -> impl fmt::Display + '_ { + display_fn(move |f| { + let real_params = self.params + .iter() + .filter(|p| !p.is_synthetic_type_param()) + .collect::>(); + if real_params.is_empty() { + return Ok(()); + } + if f.alternate() { + write!(f, "<{:#}>", comma_sep(real_params.iter().map(|g| g.print()))) + } else { + write!(f, "<{}>", comma_sep(real_params.iter().map(|g| g.print()))) + } + }) } } @@ -287,24 +268,26 @@ impl<'a> fmt::Display for WhereClause<'a> { &clean::WherePredicate::BoundPredicate { ref ty, ref bounds } => { let bounds = bounds; if f.alternate() { - clause.push_str(&format!("{:#}: {:#}", ty, GenericBounds(bounds))); + clause.push_str(&format!("{:#}: {:#}", + ty.print(), print_generic_bounds(bounds))); } else { - clause.push_str(&format!("{}: {}", ty, GenericBounds(bounds))); + clause.push_str(&format!("{}: {}", + ty.print(), print_generic_bounds(bounds))); } } &clean::WherePredicate::RegionPredicate { ref lifetime, ref bounds } => { clause.push_str(&format!("{}: {}", - lifetime, + lifetime.print(), bounds.iter() - .map(|b| b.to_string()) + .map(|b| b.print().to_string()) .collect::>() .join(" + "))); } &clean::WherePredicate::EqPredicate { ref lhs, ref rhs } => { if f.alternate() { - clause.push_str(&format!("{:#} == {:#}", lhs, rhs)); + clause.push_str(&format!("{:#} == {:#}", lhs.print(), rhs.print())); } else { - clause.push_str(&format!("{} == {}", lhs, rhs)); + clause.push_str(&format!("{} == {}", lhs.print(), rhs.print())); } } } @@ -336,153 +319,164 @@ impl<'a> fmt::Display for WhereClause<'a> { } } -impl fmt::Display for clean::Lifetime { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(self.get_ref())?; - Ok(()) +impl clean::Lifetime { + crate fn print(&self) -> &str { + self.get_ref() } } -impl fmt::Display for clean::Constant { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.expr, f) +impl clean::Constant { + crate fn print(&self) -> &str { + &self.expr } } -impl fmt::Display for clean::PolyTrait { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if !self.generic_params.is_empty() { +impl clean::PolyTrait { + fn print(&self) -> impl fmt::Display + '_ { + display_fn(move |f| { + if !self.generic_params.is_empty() { + if f.alternate() { + write!(f, "for<{:#}> ", + comma_sep(self.generic_params.iter().map(|g| g.print())))?; + } else { + write!(f, "for<{}> ", + comma_sep(self.generic_params.iter().map(|g| g.print())))?; + } + } if f.alternate() { - write!(f, "for<{:#}> ", comma_sep(&self.generic_params))?; + write!(f, "{:#}", self.trait_.print()) } else { - write!(f, "for<{}> ", comma_sep(&self.generic_params))?; + write!(f, "{}", self.trait_.print()) } - } - if f.alternate() { - write!(f, "{:#}", self.trait_) - } else { - write!(f, "{}", self.trait_) - } + }) } } -impl fmt::Display for clean::GenericBound { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - clean::GenericBound::Outlives(ref lt) => { - write!(f, "{}", *lt) - } - clean::GenericBound::TraitBound(ref ty, modifier) => { - let modifier_str = match modifier { - hir::TraitBoundModifier::None => "", - hir::TraitBoundModifier::Maybe => "?", - }; - if f.alternate() { - write!(f, "{}{:#}", modifier_str, *ty) - } else { - write!(f, "{}{}", modifier_str, *ty) +impl clean::GenericBound { + crate fn print(&self) -> impl fmt::Display + '_ { + display_fn(move |f| { + match self { + clean::GenericBound::Outlives(lt) => { + write!(f, "{}", lt.print()) + } + clean::GenericBound::TraitBound(ty, modifier) => { + let modifier_str = match modifier { + hir::TraitBoundModifier::None => "", + hir::TraitBoundModifier::Maybe => "?", + }; + if f.alternate() { + write!(f, "{}{:#}", modifier_str, ty.print()) + } else { + write!(f, "{}{}", modifier_str, ty.print()) + } } } - } + }) } } -impl fmt::Display for clean::GenericArgs { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - clean::GenericArgs::AngleBracketed { ref args, ref bindings } => { - if !args.is_empty() || !bindings.is_empty() { - if f.alternate() { - f.write_str("<")?; - } else { - f.write_str("<")?; - } - let mut comma = false; - for arg in args { - if comma { - f.write_str(", ")?; +impl clean::GenericArgs { + fn print(&self) -> impl fmt::Display + '_ { + display_fn(move |f| { + match *self { + clean::GenericArgs::AngleBracketed { ref args, ref bindings } => { + if !args.is_empty() || !bindings.is_empty() { + if f.alternate() { + f.write_str("<")?; + } else { + f.write_str("<")?; + } + let mut comma = false; + for arg in args { + if comma { + f.write_str(", ")?; + } + comma = true; + if f.alternate() { + write!(f, "{:#}", arg.print())?; + } else { + write!(f, "{}", arg.print())?; + } + } + for binding in bindings { + if comma { + f.write_str(", ")?; + } + comma = true; + if f.alternate() { + write!(f, "{:#}", binding.print())?; + } else { + write!(f, "{}", binding.print())?; + } } - comma = true; if f.alternate() { - write!(f, "{:#}", *arg)?; + f.write_str(">")?; } else { - write!(f, "{}", *arg)?; + f.write_str(">")?; } } - for binding in bindings { + } + clean::GenericArgs::Parenthesized { ref inputs, ref output } => { + f.write_str("(")?; + let mut comma = false; + for ty in inputs { if comma { f.write_str(", ")?; } comma = true; if f.alternate() { - write!(f, "{:#}", *binding)?; + write!(f, "{:#}", ty.print())?; } else { - write!(f, "{}", *binding)?; + write!(f, "{}", ty.print())?; } } - if f.alternate() { - f.write_str(">")?; - } else { - f.write_str(">")?; - } - } - } - clean::GenericArgs::Parenthesized { ref inputs, ref output } => { - f.write_str("(")?; - let mut comma = false; - for ty in inputs { - if comma { - f.write_str(", ")?; - } - comma = true; - if f.alternate() { - write!(f, "{:#}", *ty)?; - } else { - write!(f, "{}", *ty)?; - } - } - f.write_str(")")?; - if let Some(ref ty) = *output { - if f.alternate() { - write!(f, " -> {:#}", ty)?; - } else { - write!(f, " -> {}", ty)?; + f.write_str(")")?; + if let Some(ref ty) = *output { + if f.alternate() { + write!(f, " -> {:#}", ty.print())?; + } else { + write!(f, " -> {}", ty.print())?; + } } } } - } - Ok(()) + Ok(()) + }) } } -impl fmt::Display for clean::PathSegment { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&self.name)?; - if f.alternate() { - write!(f, "{:#}", self.args) - } else { - write!(f, "{}", self.args) - } +impl clean::PathSegment { + crate fn print(&self) -> impl fmt::Display + '_ { + display_fn(move |f| { + f.write_str(&self.name)?; + if f.alternate() { + write!(f, "{:#}", self.args.print()) + } else { + write!(f, "{}", self.args.print()) + } + }) } } -impl fmt::Display for clean::Path { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.global { - f.write_str("::")? - } - - for (i, seg) in self.segments.iter().enumerate() { - if i > 0 { +impl clean::Path { + crate fn print(&self) -> impl fmt::Display + '_ { + display_fn(move |f| { + if self.global { f.write_str("::")? } - if f.alternate() { - write!(f, "{:#}", seg)?; - } else { - write!(f, "{}", seg)?; + + for (i, seg) in self.segments.iter().enumerate() { + if i > 0 { + f.write_str("::")? + } + if f.alternate() { + write!(f, "{:#}", seg.print())?; + } else { + write!(f, "{}", seg.print())?; + } } - } - Ok(()) + Ok(()) + }) } } @@ -516,7 +510,7 @@ pub fn href(did: DefId) -> Option<(String, ItemType, Vec)> { url.push_str("/index.html"); } _ => { - url.push_str(shortty.css_class()); + url.push_str(shortty.as_str()); url.push_str("."); url.push_str(fqp.last().unwrap()); url.push_str(".html"); @@ -537,7 +531,7 @@ fn resolved_path(w: &mut fmt::Formatter<'_>, did: DefId, path: &clean::Path, } } if w.alternate() { - write!(w, "{}{:#}", &last.name, last.args)?; + write!(w, "{}{:#}", &last.name, last.args.print())?; } else { let path = if use_absolute { if let Some((_, _, fqp)) = href(did) { @@ -550,7 +544,7 @@ fn resolved_path(w: &mut fmt::Formatter<'_>, did: DefId, path: &clean::Path, } else { anchor(did, &last.name).to_string() }; - write!(w, "{}{}", path, last.args)?; + write!(w, "{}{}", path, last.args.print())?; } Ok(()) } @@ -606,7 +600,7 @@ fn tybounds(param_names: &Option>) -> impl fmt::Display Some(ref params) => { for param in params { write!(f, " + ")?; - fmt::Display::fmt(param, f)?; + fmt::Display::fmt(¶m.print(), f)?; } Ok(()) } @@ -646,12 +640,12 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> write!(f, "{}{:#}fn{:#}{:#}", UnsafetySpace(decl.unsafety), AbiSpace(decl.abi), - comma_sep(&decl.generic_params), - decl.decl) + decl.print_generic_params(), + decl.decl.print()) } else { write!(f, "{}{}", UnsafetySpace(decl.unsafety), AbiSpace(decl.abi))?; primitive_link(f, PrimitiveType::Fn, "fn")?; - write!(f, "{}{}", comma_sep(&decl.generic_params), decl.decl) + write!(f, "{}{}", decl.print_generic_params(), decl.decl.print()) } } clean::Tuple(ref typs) => { @@ -660,24 +654,27 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> &[ref one] => { primitive_link(f, PrimitiveType::Tuple, "(")?; // Carry `f.alternate()` into this display w/o branching manually. - fmt::Display::fmt(one, f)?; + fmt::Display::fmt(&one.print(), f)?; primitive_link(f, PrimitiveType::Tuple, ",)") } many => { primitive_link(f, PrimitiveType::Tuple, "(")?; - fmt::Display::fmt(&comma_sep(many), f)?; + for (i, item) in many.iter().enumerate() { + if i != 0 { write!(f, ", ")?; } + fmt::Display::fmt(&item.print(), f)?; + } primitive_link(f, PrimitiveType::Tuple, ")") } } } clean::Slice(ref t) => { primitive_link(f, PrimitiveType::Slice, "[")?; - fmt::Display::fmt(t, f)?; + fmt::Display::fmt(&t.print(), f)?; primitive_link(f, PrimitiveType::Slice, "]") } clean::Array(ref t, ref n) => { primitive_link(f, PrimitiveType::Array, "[")?; - fmt::Display::fmt(t, f)?; + fmt::Display::fmt(&t.print(), f)?; primitive_link(f, PrimitiveType::Array, &format!("; {}]", n)) } clean::Never => primitive_link(f, PrimitiveType::Never, "!"), @@ -691,22 +688,22 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> clean::Generic(_) | clean::ResolvedPath {is_generic: true, ..} => { if f.alternate() { primitive_link(f, clean::PrimitiveType::RawPointer, - &format!("*{} {:#}", m, t)) + &format!("*{} {:#}", m, t.print())) } else { primitive_link(f, clean::PrimitiveType::RawPointer, - &format!("*{} {}", m, t)) + &format!("*{} {}", m, t.print())) } } _ => { primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{} ", m))?; - fmt::Display::fmt(t, f) + fmt::Display::fmt(&t.print(), f) } } } clean::BorrowedRef{ lifetime: ref l, mutability, type_: ref ty} => { - let lt = match *l { - Some(ref l) => format!("{} ", *l), - _ => String::new(), + let lt = match l { + Some(l) => format!("{} ", l.print()), + _ => String::new() }; let m = MutableSpace(mutability); let amp = if f.alternate() { @@ -720,19 +717,19 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> clean::Generic(_) => { if f.alternate() { primitive_link(f, PrimitiveType::Slice, - &format!("{}{}{}[{:#}]", amp, lt, m, **bt)) + &format!("{}{}{}[{:#}]", amp, lt, m, bt.print())) } else { primitive_link(f, PrimitiveType::Slice, - &format!("{}{}{}[{}]", amp, lt, m, **bt)) + &format!("{}{}{}[{}]", amp, lt, m, bt.print())) } } _ => { primitive_link(f, PrimitiveType::Slice, &format!("{}{}{}[", amp, lt, m))?; if f.alternate() { - write!(f, "{:#}", **bt)?; + write!(f, "{:#}", bt.print())?; } else { - write!(f, "{}", **bt)?; + write!(f, "{}", bt.print())?; } primitive_link(f, PrimitiveType::Slice, "]") } @@ -756,9 +753,9 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> } clean::ImplTrait(ref bounds) => { if f.alternate() { - write!(f, "impl {:#}", GenericBounds(bounds)) + write!(f, "impl {:#}", print_generic_bounds(bounds)) } else { - write!(f, "impl {}", GenericBounds(bounds)) + write!(f, "impl {}", print_generic_bounds(bounds)) } } clean::QPath { ref name, ref self_type, ref trait_ } => { @@ -770,15 +767,15 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> }; if f.alternate() { if should_show_cast { - write!(f, "<{:#} as {:#}>::", self_type, trait_)? + write!(f, "<{:#} as {:#}>::", self_type.print(), trait_.print())? } else { - write!(f, "{:#}::", self_type)? + write!(f, "{:#}::", self_type.print())? } } else { if should_show_cast { - write!(f, "<{} as {}>::", self_type, trait_)? + write!(f, "<{} as {}>::", self_type.print(), trait_.print())? } else { - write!(f, "{}::", self_type)? + write!(f, "{}::", self_type.print())? } }; match *trait_ { @@ -818,55 +815,64 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> } } -impl fmt::Display for clean::Type { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt_type(self, f, false) +impl clean::Type { + crate fn print(&self) -> impl fmt::Display + '_ { + display_fn(move |f| { + fmt_type(self, f, false) + }) } } -fn fmt_impl(i: &clean::Impl, - f: &mut fmt::Formatter<'_>, - link_trait: bool, - use_absolute: bool) -> fmt::Result { - if f.alternate() { - write!(f, "impl{:#} ", i.generics)?; - } else { - write!(f, "impl{} ", i.generics)?; +impl clean::Impl { + crate fn print(&self) -> impl fmt::Display + '_ { + self.print_inner(true, false) } - if let Some(ref ty) = i.trait_ { - if i.polarity == Some(clean::ImplPolarity::Negative) { - write!(f, "!")?; - } + fn print_inner( + &self, + link_trait: bool, + use_absolute: bool, + ) -> impl fmt::Display + '_ { + display_fn(move |f| { + if f.alternate() { + write!(f, "impl{:#} ", self.generics.print())?; + } else { + write!(f, "impl{} ", self.generics.print())?; + } - if link_trait { - fmt::Display::fmt(ty, f)?; - } else { - match *ty { - clean::ResolvedPath { param_names: None, ref path, is_generic: false, .. } => { - let last = path.segments.last().unwrap(); - fmt::Display::fmt(&last.name, f)?; - fmt::Display::fmt(&last.args, f)?; + if let Some(ref ty) = self.trait_ { + if self.polarity == Some(clean::ImplPolarity::Negative) { + write!(f, "!")?; } - _ => unreachable!(), - } - } - write!(f, " for ")?; - } - if let Some(ref ty) = i.blanket_impl { - fmt_type(ty, f, use_absolute)?; - } else { - fmt_type(&i.for_, f, use_absolute)?; - } + if link_trait { + fmt::Display::fmt(&ty.print(), f)?; + } else { + match ty { + clean::ResolvedPath { param_names: None, path, is_generic: false, .. } => { + let last = path.segments.last().unwrap(); + fmt::Display::fmt(&last.name, f)?; + fmt::Display::fmt(&last.args.print(), f)?; + } + _ => unreachable!(), + } + } + write!(f, " for ")?; + } - fmt::Display::fmt(&WhereClause { gens: &i.generics, indent: 0, end_newline: true }, f)?; - Ok(()) -} + if let Some(ref ty) = self.blanket_impl { + fmt_type(ty, f, use_absolute)?; + } else { + fmt_type(&self.for_, f, use_absolute)?; + } -impl fmt::Display for clean::Impl { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt_impl(self, f, true, false) + fmt::Display::fmt(&WhereClause { + gens: &self.generics, + indent: 0, + end_newline: true, + }, f)?; + Ok(()) + }) } } @@ -874,162 +880,193 @@ impl fmt::Display for clean::Impl { pub fn fmt_impl_for_trait_page(i: &clean::Impl, f: &mut Buffer, use_absolute: bool) { - f.with_formatter(|f| fmt_impl(i, f, false, use_absolute)) + f.from_display(i.print_inner(false, use_absolute)) } -impl fmt::Display for clean::Arguments { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - for (i, input) in self.values.iter().enumerate() { - if !input.name.is_empty() { - write!(f, "{}: ", input.name)?; - } - if f.alternate() { - write!(f, "{:#}", input.type_)?; - } else { - write!(f, "{}", input.type_)?; +impl clean::Arguments { + crate fn print(&self) -> impl fmt::Display + '_ { + display_fn(move |f| { + for (i, input) in self.values.iter().enumerate() { + if !input.name.is_empty() { + write!(f, "{}: ", input.name)?; + } + if f.alternate() { + write!(f, "{:#}", input.type_.print())?; + } else { + write!(f, "{}", input.type_.print())?; + } + if i + 1 < self.values.len() { write!(f, ", ")?; } } - if i + 1 < self.values.len() { write!(f, ", ")?; } - } - Ok(()) + Ok(()) + }) } } -impl fmt::Display for clean::FunctionRetTy { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - clean::Return(clean::Tuple(ref tys)) if tys.is_empty() => Ok(()), - clean::Return(ref ty) if f.alternate() => write!(f, " -> {:#}", ty), - clean::Return(ref ty) => write!(f, " -> {}", ty), - clean::DefaultReturn => Ok(()), - } +impl clean::FunctionRetTy { + crate fn print(&self) -> impl fmt::Display + '_ { + display_fn(move |f| { + match self { + clean::Return(clean::Tuple(tys)) if tys.is_empty() => Ok(()), + clean::Return(ty) if f.alternate() => write!(f, " -> {:#}", ty.print()), + clean::Return(ty) => write!(f, " -> {}", ty.print()), + clean::DefaultReturn => Ok(()), + } + }) } } -impl fmt::Display for clean::FnDecl { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if f.alternate() { - write!(f, "({args:#}){arrow:#}", args = self.inputs, arrow = self.output) - } else { - write!(f, "({args}){arrow}", args = self.inputs, arrow = self.output) - } +impl clean::BareFunctionDecl { + fn print_generic_params(&self) -> impl fmt::Display + '_ { + comma_sep(self.generic_params.iter().map(|g| g.print())) } } -impl<'a> fmt::Display for Function<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let &Function { decl, header_len, indent, asyncness } = self; - let amp = if f.alternate() { "&" } else { "&" }; - let mut args = String::new(); - let mut args_plain = String::new(); - for (i, input) in decl.inputs.values.iter().enumerate() { - if i == 0 { - args.push_str("
"); +impl clean::FnDecl { + crate fn print(&self) -> impl fmt::Display + '_ { + display_fn(move |f| { + if f.alternate() { + write!(f, + "({args:#}){arrow:#}", args = self.inputs.print(), arrow = self.output.print()) + } else { + write!(f, + "({args}){arrow}", args = self.inputs.print(), arrow = self.output.print()) } + }) + } +} + + +impl Function<'_> { + crate fn print(&self) -> impl fmt::Display + '_ { + display_fn(move |f| { + let &Function { decl, header_len, indent, asyncness } = self; + let amp = if f.alternate() { "&" } else { "&" }; + let mut args = String::new(); + let mut args_plain = String::new(); + for (i, input) in decl.inputs.values.iter().enumerate() { + if i == 0 { + args.push_str("
"); + } - if let Some(selfty) = input.to_self() { - match selfty { - clean::SelfValue => { - args.push_str("self"); - args_plain.push_str("self"); + if let Some(selfty) = input.to_self() { + match selfty { + clean::SelfValue => { + args.push_str("self"); + args_plain.push_str("self"); + } + clean::SelfBorrowed(Some(ref lt), mtbl) => { + args.push_str( + &format!("{}{} {}self", amp, lt.print(), MutableSpace(mtbl))); + args_plain.push_str( + &format!("&{} {}self", lt.print(), MutableSpace(mtbl))); + } + clean::SelfBorrowed(None, mtbl) => { + args.push_str(&format!("{}{}self", amp, MutableSpace(mtbl))); + args_plain.push_str(&format!("&{}self", MutableSpace(mtbl))); + } + clean::SelfExplicit(ref typ) => { + if f.alternate() { + args.push_str(&format!("self: {:#}", typ.print())); + } else { + args.push_str(&format!("self: {}", typ.print())); + } + args_plain.push_str(&format!("self: {:#}", typ.print())); + } } - clean::SelfBorrowed(Some(ref lt), mtbl) => { - args.push_str(&format!("{}{} {}self", amp, *lt, MutableSpace(mtbl))); - args_plain.push_str(&format!("&{} {}self", *lt, MutableSpace(mtbl))); + } else { + if i > 0 { + args.push_str("
"); + args_plain.push_str(" "); } - clean::SelfBorrowed(None, mtbl) => { - args.push_str(&format!("{}{}self", amp, MutableSpace(mtbl))); - args_plain.push_str(&format!("&{}self", MutableSpace(mtbl))); + if !input.name.is_empty() { + args.push_str(&format!("{}: ", input.name)); + args_plain.push_str(&format!("{}: ", input.name)); } - clean::SelfExplicit(ref typ) => { - if f.alternate() { - args.push_str(&format!("self: {:#}", *typ)); - } else { - args.push_str(&format!("self: {}", *typ)); - } - args_plain.push_str(&format!("self: {:#}", *typ)); + + if f.alternate() { + args.push_str(&format!("{:#}", input.type_.print())); + } else { + args.push_str(&input.type_.print().to_string()); } + args_plain.push_str(&format!("{:#}", input.type_.print())); } - } else { - if i > 0 { - args.push_str("
"); - args_plain.push_str(" "); - } - if !input.name.is_empty() { - args.push_str(&format!("{}: ", input.name)); - args_plain.push_str(&format!("{}: ", input.name)); + if i + 1 < decl.inputs.values.len() { + args.push(','); + args_plain.push(','); } - - if f.alternate() { - args.push_str(&format!("{:#}", input.type_)); - } else { - args.push_str(&input.type_.to_string()); - } - args_plain.push_str(&format!("{:#}", input.type_)); } - if i + 1 < decl.inputs.values.len() { - args.push(','); - args_plain.push(','); - } - } - let args_plain = format!("({})", args_plain); + let args_plain = format!("({})", args_plain); - let output = if let hir::IsAsync::Async = asyncness { - Cow::Owned(decl.sugared_async_return_type()) - } else { - Cow::Borrowed(&decl.output) - }; + let output = if let hir::IsAsync::Async = asyncness { + Cow::Owned(decl.sugared_async_return_type()) + } else { + Cow::Borrowed(&decl.output) + }; - let arrow_plain = format!("{:#}", &output); - let arrow = if f.alternate() { - format!("{:#}", &output) - } else { - output.to_string() - }; + let arrow_plain = format!("{:#}", &output.print()); + let arrow = if f.alternate() { + format!("{:#}", &output.print()) + } else { + output.print().to_string() + }; - let declaration_len = header_len + args_plain.len() + arrow_plain.len(); - let output = if declaration_len > 80 { - let full_pad = format!("
{}", " ".repeat(indent + 4)); - let close_pad = format!("
{}", " ".repeat(indent)); - format!("({args}{close}){arrow}", - args = args.replace("
", &full_pad), - close = close_pad, - arrow = arrow) - } else { - format!("({args}){arrow}", args = args.replace("
", ""), arrow = arrow) - }; + let declaration_len = header_len + args_plain.len() + arrow_plain.len(); + let output = if declaration_len > 80 { + let full_pad = format!("
{}", " ".repeat(indent + 4)); + let close_pad = format!("
{}", " ".repeat(indent)); + format!("({args}{close}){arrow}", + args = args.replace("
", &full_pad), + close = close_pad, + arrow = arrow) + } else { + format!("({args}){arrow}", args = args.replace("
", ""), arrow = arrow) + }; - if f.alternate() { - write!(f, "{}", output.replace("
", "\n")) - } else { - write!(f, "{}", output) - } + if f.alternate() { + write!(f, "{}", output.replace("
", "\n")) + } else { + write!(f, "{}", output) + } + }) } } impl<'a> fmt::Display for VisSpace<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self.get() { - Some(clean::Public) => f.write_str("pub "), - Some(clean::Inherited) | None => Ok(()), - Some(clean::Visibility::Crate) => write!(f, "pub(crate) "), - Some(clean::Visibility::Restricted(did, ref path)) => { - f.write_str("pub(")?; - if path.segments.len() != 1 - || (path.segments[0].name != "self" && path.segments[0].name != "super") - { - f.write_str("in ")?; + if let Some(v) = self.0 { + fmt::Display::fmt(&v.print_with_space(), f) + } else { + Ok(()) + } + } +} + +impl clean::Visibility { + fn print_with_space(&self) -> impl fmt::Display + '_ { + display_fn(move |f| { + match *self { + clean::Public => f.write_str("pub "), + clean::Inherited => Ok(()), + clean::Visibility::Crate => write!(f, "pub(crate) "), + clean::Visibility::Restricted(did, ref path) => { + f.write_str("pub(")?; + if path.segments.len() != 1 + || (path.segments[0].name != "self" && path.segments[0].name != "super") + { + f.write_str("in ")?; + } + resolved_path(f, did, path, true, false)?; + f.write_str(") ") } - resolved_path(f, did, path, true, false)?; - f.write_str(") ") } - } + }) } } impl fmt::Display for UnsafetySpace { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.get() { + match self.0 { hir::Unsafety::Unsafe => write!(f, "unsafe "), hir::Unsafety::Normal => Ok(()) } @@ -1038,7 +1075,7 @@ impl fmt::Display for UnsafetySpace { impl fmt::Display for ConstnessSpace { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.get() { + match self.0 { hir::Constness::Const => write!(f, "const "), hir::Constness::NotConst => Ok(()) } @@ -1054,66 +1091,72 @@ impl fmt::Display for AsyncSpace { } } -impl fmt::Display for clean::Import { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - clean::Import::Simple(ref name, ref src) => { - if *name == src.path.last_name() { - write!(f, "use {};", *src) - } else { - write!(f, "use {} as {};", *src, *name) +impl clean::Import { + crate fn print(&self) -> impl fmt::Display + '_ { + display_fn(move |f| { + match *self { + clean::Import::Simple(ref name, ref src) => { + if *name == src.path.last_name() { + write!(f, "use {};", src.print()) + } else { + write!(f, "use {} as {};", src.print(), *name) + } } - } - clean::Import::Glob(ref src) => { - if src.path.segments.is_empty() { - write!(f, "use *;") - } else { - write!(f, "use {}::*;", *src) + clean::Import::Glob(ref src) => { + if src.path.segments.is_empty() { + write!(f, "use *;") + } else { + write!(f, "use {}::*;", src.print()) + } } } - } + }) } } -impl fmt::Display for clean::ImportSource { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.did { - Some(did) => resolved_path(f, did, &self.path, true, false), - _ => { - for (i, seg) in self.path.segments.iter().enumerate() { - if i > 0 { - write!(f, "::")? +impl clean::ImportSource { + crate fn print(&self) -> impl fmt::Display + '_ { + display_fn(move |f| { + match self.did { + Some(did) => resolved_path(f, did, &self.path, true, false), + _ => { + for (i, seg) in self.path.segments.iter().enumerate() { + if i > 0 { + write!(f, "::")? + } + write!(f, "{}", seg.name)?; } - write!(f, "{}", seg.name)?; + Ok(()) } - Ok(()) } - } + }) } } -impl fmt::Display for clean::TypeBinding { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&self.name)?; - match self.kind { - clean::TypeBindingKind::Equality { ref ty } => { - if f.alternate() { - write!(f, " = {:#}", ty)?; - } else { - write!(f, " = {}", ty)?; - } - } - clean::TypeBindingKind::Constraint { ref bounds } => { - if !bounds.is_empty() { +impl clean::TypeBinding { + crate fn print(&self) -> impl fmt::Display + '_ { + display_fn(move |f| { + f.write_str(&self.name)?; + match self.kind { + clean::TypeBindingKind::Equality { ref ty } => { if f.alternate() { - write!(f, ": {:#}", GenericBounds(bounds))?; + write!(f, " = {:#}", ty.print())?; } else { - write!(f, ": {}", GenericBounds(bounds))?; + write!(f, " = {}", ty.print())?; + } + } + clean::TypeBindingKind::Constraint { ref bounds } => { + if !bounds.is_empty() { + if f.alternate() { + write!(f, ": {:#}", print_generic_bounds(bounds))?; + } else { + write!(f, ": {}", print_generic_bounds(bounds))?; + } } } } - } - Ok(()) + Ok(()) + }) } } @@ -1146,6 +1189,18 @@ impl fmt::Display for DefaultSpace { } } +impl clean::GenericArg { + crate fn print(&self) -> impl fmt::Display + '_ { + display_fn(move |f| { + match self { + clean::GenericArg::Lifetime(lt) => fmt::Display::fmt(<.print(), f), + clean::GenericArg::Type(ty) => fmt::Display::fmt(&ty.print(), f), + clean::GenericArg::Const(ct) => fmt::Display::fmt(&ct.print(), f), + } + }) + } +} + crate fn display_fn( f: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, ) -> impl fmt::Display { diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index cf51a4eb5a5be..5fb9afd6c49a0 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -46,14 +46,6 @@ pub enum ItemType { } -#[derive(Copy, Eq, PartialEq, Clone)] -pub enum NameSpace { - Type, - Value, - Macro, - Keyword, -} - impl<'a> From<&'a clean::Item> for ItemType { fn from(item: &'a clean::Item) -> ItemType { let inner = match item.inner { @@ -120,7 +112,7 @@ impl From for ItemType { } impl ItemType { - pub fn css_class(&self) -> &'static str { + pub fn as_str(&self) -> &'static str { match *self { ItemType::Module => "mod", ItemType::ExternCrate => "externcrate", @@ -151,7 +143,7 @@ impl ItemType { } } - pub fn name_space(&self) -> NameSpace { + pub fn name_space(&self) -> &'static str { match *self { ItemType::Struct | ItemType::Union | @@ -163,7 +155,7 @@ impl ItemType { ItemType::AssocType | ItemType::OpaqueTy | ItemType::TraitAlias | - ItemType::ForeignType => NameSpace::Type, + ItemType::ForeignType => NAMESPACE_TYPE, ItemType::ExternCrate | ItemType::Import | @@ -175,20 +167,20 @@ impl ItemType { ItemType::StructField | ItemType::Variant | ItemType::Constant | - ItemType::AssocConst => NameSpace::Value, + ItemType::AssocConst => NAMESPACE_VALUE, ItemType::Macro | ItemType::ProcAttribute | - ItemType::ProcDerive => NameSpace::Macro, + ItemType::ProcDerive => NAMESPACE_MACRO, - ItemType::Keyword => NameSpace::Keyword, + ItemType::Keyword => NAMESPACE_KEYWORD, } } } impl fmt::Display for ItemType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.css_class().fmt(f) + write!(f, "{}", self.as_str()) } } @@ -196,20 +188,3 @@ pub const NAMESPACE_TYPE: &'static str = "t"; pub const NAMESPACE_VALUE: &'static str = "v"; pub const NAMESPACE_MACRO: &'static str = "m"; pub const NAMESPACE_KEYWORD: &'static str = "k"; - -impl NameSpace { - pub fn to_static_str(&self) -> &'static str { - match *self { - NameSpace::Type => NAMESPACE_TYPE, - NameSpace::Value => NAMESPACE_VALUE, - NameSpace::Macro => NAMESPACE_MACRO, - NameSpace::Keyword => NAMESPACE_KEYWORD, - } - } -} - -impl fmt::Display for NameSpace { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.to_static_str().fmt(f) - } -} diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 9846073cad4bc..7aaf04f34d32f 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -66,7 +66,7 @@ use crate::doctree; use crate::fold::DocFolder; use crate::html::escape::Escape; use crate::html::format::{Buffer, AsyncSpace, ConstnessSpace}; -use crate::html::format::{GenericBounds, WhereClause, href, AbiSpace, DefaultSpace}; +use crate::html::format::{print_generic_bounds, WhereClause, href, AbiSpace, DefaultSpace}; use crate::html::format::{VisSpace, Function, UnsafetySpace, MutableSpace}; use crate::html::format::fmt_impl_for_trait_page; use crate::html::item_type::ItemType; @@ -1203,7 +1203,7 @@ themePicker.onblur = handleThemeButtonsBlur; if !imp.impl_item.def_id.is_local() { continue } have_impls = true; write!(implementors, "{{text:{},synthetic:{},types:{}}},", - as_json(&imp.inner_impl().to_string()), + as_json(&imp.inner_impl().print().to_string()), imp.inner_impl().synthetic, as_json(&collect_paths_for_type(imp.inner_impl().for_.clone()))).unwrap(); } @@ -1222,7 +1222,7 @@ themePicker.onblur = handleThemeButtonsBlur; } cx.shared.ensure_dir(&mydst)?; mydst.push(&format!("{}.{}.js", - remote_item_type.css_class(), + remote_item_type, remote_path[remote_path.len() - 1])); let (mut all_implementors, _, _) = try_err!(collect(&mydst, &krate.name, "implementors", @@ -1665,9 +1665,11 @@ impl ItemEntry { } } -impl fmt::Display for ItemEntry { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.url, Escape(&self.name)) +impl ItemEntry { + crate fn print(&self) -> impl fmt::Display + '_ { + crate::html::format::display_fn(move |f| { + write!(f, "{}", self.url, Escape(&self.name)) + }) } } @@ -1759,7 +1761,7 @@ fn print_entries(f: &mut Buffer, e: &FxHashSet, title: &str, class: & title, Escape(title), class, - e.iter().map(|s| format!("
  • {}
  • ", s)).collect::()); + e.iter().map(|s| format!("
  • {}
  • ", s.print())).collect::()); } } @@ -1939,7 +1941,7 @@ impl Context { title.push_str(it.name.as_ref().unwrap()); } title.push_str(" - Rust"); - let tyname = it.type_().css_class(); + let tyname = it.type_(); let desc = if it.is_crate() { format!("API documentation for the Rust `{}` crate.", self.shared.layout.krate) @@ -1949,7 +1951,7 @@ impl Context { }; let keywords = make_item_keywords(it); let page = layout::Page { - css_class: tyname, + css_class: tyname.as_str(), root_path: &self.root_path(), static_root_path: self.shared.static_root_path.as_deref(), title: &title, @@ -2090,7 +2092,7 @@ impl Context { for item in &m.items { if item.is_stripped() { continue } - let short = item.type_().css_class(); + let short = item.type_(); let myname = match item.name { None => continue, Some(ref s) => s.to_string(), @@ -2285,7 +2287,7 @@ fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer) { fn item_path(ty: ItemType, name: &str) -> String { match ty { ItemType::Module => format!("{}index.html", SlashChecker(name)), - _ => format!("{}.{}.html", ty.css_class(), name), + _ => format!("{}.{}.html", ty, name), } } @@ -2586,7 +2588,7 @@ fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean: clean::ImportItem(ref import) => { write!(w, "{}{}", - VisSpace(&myitem.visibility), *import); + VisSpace(&myitem.visibility), import.print()); } _ => { @@ -2794,7 +2796,7 @@ fn item_constant(w: &mut Buffer, cx: &Context, it: &clean::Item, c: &clean::Cons {name}: {typ}", vis = VisSpace(&it.visibility), name = it.name.as_ref().unwrap(), - typ = c.type_); + typ = c.type_.print()); document(w, cx, it) } @@ -2806,7 +2808,7 @@ fn item_static(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Static vis = VisSpace(&it.visibility), mutability = MutableSpace(s.mutability), name = it.name.as_ref().unwrap(), - typ = s.type_); + typ = s.type_.print()); document(w, cx, it) } @@ -2819,7 +2821,7 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func AsyncSpace(f.header.asyncness), AbiSpace(f.header.abi), it.name.as_ref().unwrap(), - f.generics + f.generics.print() ).len(); write!(w, "{}
    ", render_spotlight_traits(it));
         render_attributes(w, it, false);
    @@ -2832,14 +2834,14 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
                asyncness = AsyncSpace(f.header.asyncness),
                abi = AbiSpace(f.header.abi),
                name = it.name.as_ref().unwrap(),
    -           generics = f.generics,
    +           generics = f.generics.print(),
                where_clause = WhereClause { gens: &f.generics, indent: 0, end_newline: true },
                decl = Function {
                   decl: &f.decl,
                   header_len,
                   indent: 0,
                   asyncness: f.header.asyncness,
    -           });
    +           }.print());
         document(w, cx, it)
     }
     
    @@ -2880,15 +2882,15 @@ fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool) -> String {
                 if i > 0 {
                     bounds.push_str(" + ");
                 }
    -            bounds.push_str(&(*p).to_string());
    +            bounds.push_str(&p.print().to_string());
             }
         }
         bounds
     }
     
     fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl) -> Ordering {
    -    let lhs = format!("{}", lhs.inner_impl());
    -    let rhs = format!("{}", rhs.inner_impl());
    +    let lhs = format!("{}", lhs.inner_impl().print());
    +    let rhs = format!("{}", rhs.inner_impl().print());
     
         // lhs and rhs are formatted as HTML, which may be unnecessary
         name_key(&lhs).cmp(&name_key(&rhs))
    @@ -2915,7 +2917,7 @@ fn item_trait(
                    UnsafetySpace(t.unsafety),
                    if t.is_auto { "auto " } else { "" },
                    it.name.as_ref().unwrap(),
    -               t.generics,
    +               t.generics.print(),
                    bounds);
     
             if !t.generics.where_predicates.is_empty() {
    @@ -3142,7 +3144,7 @@ fn item_trait(
                    let (ref path, _) = cache.external_paths[&it.def_id];
                    path[..path.len() - 1].join("/")
                },
    -           ty = it.type_().css_class(),
    +           ty = it.type_(),
                name = *it.name.as_ref().unwrap());
     }
     
    @@ -3176,7 +3178,7 @@ fn assoc_const(w: &mut Buffer,
                VisSpace(&it.visibility),
                naive_assoc_href(it, link),
                it.name.as_ref().unwrap(),
    -           ty);
    +           ty.print());
     }
     
     fn assoc_type(w: &mut Buffer, it: &clean::Item,
    @@ -3189,10 +3191,10 @@ fn assoc_type(w: &mut Buffer, it: &clean::Item,
                naive_assoc_href(it, link),
                it.name.as_ref().unwrap());
         if !bounds.is_empty() {
    -        write!(w, ": {}", GenericBounds(bounds))
    +        write!(w, ": {}", print_generic_bounds(bounds))
         }
         if let Some(default) = default {
    -        write!(w, " = {}", default)
    +        write!(w, " = {}", default.print())
         }
     }
     
    @@ -3245,7 +3247,7 @@ fn render_assoc_item(w: &mut Buffer,
                 DefaultSpace(meth.is_default()),
                 AbiSpace(header.abi),
                 name,
    -            *g
    +            g.print()
             ).len();
             let (indent, end_newline) = if parent == ItemType::Trait {
                 header_len += 4;
    @@ -3265,13 +3267,13 @@ fn render_assoc_item(w: &mut Buffer,
                    AbiSpace(header.abi),
                    href = href,
                    name = name,
    -               generics = *g,
    +               generics = g.print(),
                    decl = Function {
                        decl: d,
                        header_len,
                        indent,
                        asyncness: header.asyncness,
    -               },
    +               }.print(),
                    where_clause = WhereClause {
                        gens: g,
                        indent,
    @@ -3340,7 +3342,7 @@ fn item_struct(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Struct
                            id = id,
                            ns_id = ns_id,
                            name = field.name.as_ref().unwrap(),
    -                       ty = ty);
    +                       ty = ty.print());
                     document(w, cx, field);
                 }
             }
    @@ -3381,7 +3383,7 @@ fn item_union(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Union)
                        id = id,
                        name = name,
                        shortty = ItemType::StructField,
    -                   ty = ty);
    +                   ty = ty.print());
                 if let Some(stability_class) = field.stability_class() {
                     write!(w, "",
                         stab = stability_class);
    @@ -3399,7 +3401,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) {
             write!(w, "{}enum {}{}{}",
                    VisSpace(&it.visibility),
                    it.name.as_ref().unwrap(),
    -               e.generics,
    +               e.generics.print(),
                    WhereClause { gens: &e.generics, indent: 0, end_newline: true });
             if e.variants.is_empty() && !e.variants_stripped {
                 write!(w, " {{}}");
    @@ -3418,7 +3420,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) {
                                         if i > 0 {
                                             write!(w, ", ")
                                         }
    -                                    write!(w, "{}", *ty);
    +                                    write!(w, "{}", ty.print());
                                     }
                                     write!(w, ")");
                                 }
    @@ -3472,7 +3474,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) {
                             if i > 0 {
                                 write!(w, ", ");
                             }
    -                        write!(w, "{}", *ty);
    +                        write!(w, "{}", ty.print());
                         }
                         write!(w, ")");
                     }
    @@ -3510,7 +3512,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) {
                                    id = id,
                                    ns_id = ns_id,
                                    f = field.name.as_ref().unwrap(),
    -                               t = *ty);
    +                               t = ty.print());
                             document(w, cx, field);
                         }
                     }
    @@ -3590,7 +3592,7 @@ fn render_struct(w: &mut Buffer, it: &clean::Item,
                if structhead {"struct "} else {""},
                it.name.as_ref().unwrap());
         if let Some(g) = g {
    -        write!(w, "{}", g)
    +        write!(w, "{}", g.print())
         }
         match ty {
             doctree::Plain => {
    @@ -3605,7 +3607,7 @@ fn render_struct(w: &mut Buffer, it: &clean::Item,
                                tab,
                                VisSpace(&field.visibility),
                                field.name.as_ref().unwrap(),
    -                           *ty);
    +                           ty.print());
                         has_visible_fields = true;
                     }
                 }
    @@ -3633,7 +3635,7 @@ fn render_struct(w: &mut Buffer, it: &clean::Item,
                             write!(w, "_")
                         }
                         clean::StructFieldItem(ref ty) => {
    -                        write!(w, "{}{}", VisSpace(&field.visibility), *ty)
    +                        write!(w, "{}{}", VisSpace(&field.visibility), ty.print())
                         }
                         _ => unreachable!()
                     }
    @@ -3664,7 +3666,7 @@ fn render_union(w: &mut Buffer, it: &clean::Item,
                if structhead {"union "} else {""},
                it.name.as_ref().unwrap());
         if let Some(g) = g {
    -        write!(w, "{}", g);
    +        write!(w, "{}", g.print());
             write!(w, "{}", WhereClause { gens: g, indent: 0, end_newline: true });
         }
     
    @@ -3674,7 +3676,7 @@ fn render_union(w: &mut Buffer, it: &clean::Item,
                 write!(w, "    {}{}: {},\n{}",
                        VisSpace(&field.visibility),
                        field.name.as_ref().unwrap(),
    -                   *ty,
    +                   ty.print(),
                        tab);
             }
         }
    @@ -3740,7 +3742,7 @@ fn render_assoc_items(w: &mut Buffer,
                           Methods from {}<Target = {}>\
                           \
                         \
    -                ", trait_, type_);
    +                ", trait_.print(), type_.print());
                     RenderMode::ForDeref { mut_: deref_mut_ }
                 }
             };
    @@ -3885,12 +3887,13 @@ fn spotlight_decl(decl: &clean::FnDecl) -> String {
                             out.push_str(
                                 &format!("

    Important traits for {}

    \ ", - impl_.for_)); - trait_.push_str(&impl_.for_.to_string()); + impl_.for_.print())); + trait_.push_str(&impl_.for_.print().to_string()); } //use the "where" class here to make it small - out.push_str(&format!("{}", impl_)); + out.push_str( + &format!("{}", impl_.print())); let t_did = impl_.trait_.def_id().unwrap(); for it in &impl_.items { if let clean::TypedefItem(ref tydef, _) = it.inner { @@ -3927,7 +3930,7 @@ fn render_impl(w: &mut Buffer, cx: &Context, i: &Impl, link: AssocItemLink<'_>, Some(ref t) => if is_on_foreign_type { get_id_for_impl_on_foreign_type(&i.inner_impl().for_, t) } else { - format!("impl-{}", small_url_encode(&format!("{:#}", t))) + format!("impl-{}", small_url_encode(&format!("{:#}", t.print()))) }, None => "impl".to_string(), }); @@ -3948,7 +3951,7 @@ fn render_impl(w: &mut Buffer, cx: &Context, i: &Impl, link: AssocItemLink<'_>, write!(w, ""); } else { write!(w, "

    {}", - id, i.inner_impl() + id, i.inner_impl().print() ); } write!(w, "", id); @@ -3993,8 +3996,10 @@ fn render_impl(w: &mut Buffer, cx: &Context, i: &Impl, link: AssocItemLink<'_>, // Only render when the method is not static or we allow static methods if render_method_item { let id = cx.derive_id(format!("{}.{}", item_type, name)); - let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space())); - write!(w, "

    ", id, item_type, extra_class); + let ns_id = cx.derive_id(format!("{}.{}", + name, item_type.name_space())); + write!(w, "

    ", + id, item_type, extra_class); write!(w, "{}", spotlight_decl(decl)); write!(w, "", ns_id); render_assoc_item(w, item, link.anchor(&id), ItemType::Impl); @@ -4125,7 +4130,7 @@ fn item_opaque_ty( render_attributes(w, it, false); write!(w, "type {}{}{where_clause} = impl {bounds};

    ", it.name.as_ref().unwrap(), - t.generics, + t.generics.print(), where_clause = WhereClause { gens: &t.generics, indent: 0, end_newline: true }, bounds = bounds(&t.bounds, false)); @@ -4144,7 +4149,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context, it: &clean::Item, render_attributes(w, it, false); write!(w, "trait {}{}{} = {};", it.name.as_ref().unwrap(), - t.generics, + t.generics.print(), WhereClause { gens: &t.generics, indent: 0, end_newline: true }, bounds(&t.bounds, true)); @@ -4162,9 +4167,9 @@ fn item_typedef(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Typed render_attributes(w, it, false); write!(w, "type {}{}{where_clause} = {type_};", it.name.as_ref().unwrap(), - t.generics, + t.generics.print(), where_clause = WhereClause { gens: &t.generics, indent: 0, end_newline: true }, - type_ = t.type_); + type_ = t.type_.print()); document(w, cx, it); @@ -4269,7 +4274,7 @@ fn print_sidebar(cx: &Context, it: &clean::Item, buffer: &mut Buffer) { relpath: '{path}'\ }};", name = it.name.as_ref().map(|x| &x[..]).unwrap_or(""), - ty = it.type_().css_class(), + ty = it.type_(), path = relpath); if parentlen == 0 { // There is no sidebar-items.js beyond the crate root path @@ -4370,9 +4375,10 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { if let Some(impls) = inner_impl { out.push_str(""); out.push_str(&format!("Methods from {}<Target={}>", - Escape(&format!("{:#}", - impl_.inner_impl().trait_.as_ref().unwrap())), - Escape(&format!("{:#}", target)))); + Escape(&format!( + "{:#}", impl_.inner_impl().trait_.as_ref().unwrap().print() + )), + Escape(&format!("{:#}", target.print())))); out.push_str(""); let mut ret = impls.iter() .filter(|i| i.inner_impl().trait_.is_none()) @@ -4397,9 +4403,9 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { .filter_map(|i| { let is_negative_impl = is_negative_impl(i.inner_impl()); if let Some(ref i) = i.inner_impl().trait_ { - let i_display = format!("{:#}", i); + let i_display = format!("{:#}", i.print()); let out = Escape(&i_display); - let encoded = small_url_encode(&format!("{:#}", i)); + let encoded = small_url_encode(&format!("{:#}", i.print())); let generated = format!("{}{}", encoded, if is_negative_impl { "!" } else { "" }, @@ -4471,14 +4477,17 @@ fn sidebar_struct(buf: &mut Buffer, it: &clean::Item, s: &clean::Struct) { } fn get_id_for_impl_on_foreign_type(for_: &clean::Type, trait_: &clean::Type) -> String { - small_url_encode(&format!("impl-{:#}-for-{:#}", trait_, for_)) + small_url_encode(&format!("impl-{:#}-for-{:#}", trait_.print(), for_.print())) } fn extract_for_impl_name(item: &clean::Item) -> Option<(String, String)> { match item.inner { clean::ItemEnum::ImplItem(ref i) => { if let Some(ref trait_) = i.trait_ { - Some((format!("{:#}", i.for_), get_id_for_impl_on_foreign_type(&i.for_, trait_))) + Some(( + format!("{:#}", i.for_.print()), + get_id_for_impl_on_foreign_type(&i.for_, trait_), + )) } else { None } diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 4ee09f7096b61..dc1ca8d7668ae 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -142,7 +142,8 @@ impl fold::DocFolder for CoverageCalculator { } clean::ImplItem(ref impl_) => { if let Some(ref tr) = impl_.trait_ { - debug!("impl {:#} for {:#} in {}", tr, impl_.for_, i.source.filename); + debug!("impl {:#} for {:#} in {}", + tr.print(), impl_.for_.print(), i.source.filename); // don't count trait impls, the missing-docs lint doesn't so we shouldn't // either @@ -151,11 +152,11 @@ impl fold::DocFolder for CoverageCalculator { // inherent impls *can* be documented, and those docs show up, but in most // cases it doesn't make sense, as all methods on a type are in one single // impl block - debug!("impl {:#} in {}", impl_.for_, i.source.filename); + debug!("impl {:#} in {}", impl_.for_.print(), i.source.filename); } } _ => { - debug!("counting {} {:?} in {}", i.type_(), i.name, i.source.filename); + debug!("counting {:?} {:?} in {}", i.type_(), i.name, i.source.filename); self.items.entry(i.source.filename.clone()) .or_default() .count_item(has_docs); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index d6073cdc1e11d..b67f39d328015 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -237,7 +237,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { }); if parent_node.is_some() { - debug!("got parent node for {} {:?}, id {:?}", item.type_(), item.name, item.def_id); + debug!("got parent node for {:?} {:?}, id {:?}", item.type_(), item.name, item.def_id); } let current_item = match item.inner { diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 14f8b16dc3067..d0f2cdad8f3e4 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -153,7 +153,7 @@ impl<'a> DocFolder for Stripper<'a> { // We need to recurse into stripped modules to strip things // like impl methods but when doing so we must not add any // items to the `retained` set. - debug!("Stripper: recursing into stripped {} {:?}", i.type_(), i.name); + debug!("Stripper: recursing into stripped {:?} {:?}", i.type_(), i.name); let old = mem::replace(&mut self.update_retained, false); let ret = self.fold_item_recur(i); self.update_retained = old; @@ -178,7 +178,7 @@ impl<'a> DocFolder for Stripper<'a> { | clean::ForeignTypeItem => { if i.def_id.is_local() { if !self.access_levels.is_exported(i.def_id) { - debug!("Stripper: stripping {} {:?}", i.type_(), i.name); + debug!("Stripper: stripping {:?} {:?}", i.type_(), i.name); return None; } } diff --git a/src/librustdoc/passes/strip_hidden.rs b/src/librustdoc/passes/strip_hidden.rs index da8977544f64b..0159e03f6f299 100644 --- a/src/librustdoc/passes/strip_hidden.rs +++ b/src/librustdoc/passes/strip_hidden.rs @@ -39,7 +39,7 @@ struct Stripper<'a> { impl<'a> DocFolder for Stripper<'a> { fn fold_item(&mut self, i: Item) -> Option { if i.attrs.lists(sym::doc).has_word(sym::hidden) { - debug!("strip_hidden: stripping {} {:?}", i.type_(), i.name); + debug!("strip_hidden: stripping {:?} {:?}", i.type_(), i.name); // use a dedicated hidden item for given item type if any match i.inner { clean::StructFieldItem(..) | clean::ModuleItem(..) => { From ec349bef24dc6faf41970bc7de17d22bce6a7cfb Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Thu, 12 Sep 2019 22:32:12 -0400 Subject: [PATCH 018/413] Unwrap Visibility fields There's not really any reason to not have the visibility default to inherited, and this saves us the trouble of checking everywhere for whether we have a visibility or not. --- src/librustdoc/clean/auto_trait.rs | 2 +- src/librustdoc/clean/blanket_impl.rs | 2 +- src/librustdoc/clean/inline.rs | 4 ++-- src/librustdoc/clean/mod.rs | 32 ++++++++++++++-------------- src/librustdoc/html/format.rs | 8 ++----- src/librustdoc/html/render.rs | 5 ++--- src/librustdoc/passes/mod.rs | 6 +++--- 7 files changed, 27 insertions(+), 32 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 516be99ed6aad..18a84cd0eeb76 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -119,7 +119,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { source: Span::empty(), name: None, attrs: Default::default(), - visibility: None, + visibility: Inherited, def_id: self.cx.next_def_id(param_env_def_id.krate), stability: None, deprecation: None, diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 490d4107c51ab..4cd1cc1a1cf50 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -99,7 +99,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { source: self.cx.tcx.def_span(impl_def_id).clean(self.cx), name: None, attrs: Default::default(), - visibility: None, + visibility: Inherited, def_id: self.cx.next_def_id(impl_def_id.krate), stability: None, deprecation: None, diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index cb42ff1c8052f..031e77ff1dbe0 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -131,7 +131,7 @@ pub fn try_inline( name: Some(name.clean(cx)), attrs, inner, - visibility: Some(clean::Public), + visibility: clean::Public, stability: cx.tcx.lookup_stability(did).clean(cx), deprecation: cx.tcx.lookup_deprecation(did).clean(cx), def_id: did, @@ -418,7 +418,7 @@ pub fn build_impl(cx: &DocContext<'_>, did: DefId, attrs: Option>, source: tcx.def_span(did).clean(cx), name: None, attrs, - visibility: Some(clean::Inherited), + visibility: clean::Inherited, stability: tcx.lookup_stability(did).clean(cx), deprecation: tcx.lookup_deprecation(did).clean(cx), def_id: did, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 10c4231b82eeb..197c09ba759e7 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -187,7 +187,7 @@ pub fn krate(mut cx: &mut DocContext<'_>) -> Crate { source: Span::empty(), name: Some(prim.to_url_str().to_string()), attrs: attrs.clone(), - visibility: Some(Public), + visibility: Public, stability: get_stability(cx, def_id), deprecation: get_deprecation(cx, def_id), def_id, @@ -199,7 +199,7 @@ pub fn krate(mut cx: &mut DocContext<'_>) -> Crate { source: Span::empty(), name: Some(kw.clone()), attrs: attrs, - visibility: Some(Public), + visibility: Public, stability: get_stability(cx, def_id), deprecation: get_deprecation(cx, def_id), def_id, @@ -361,7 +361,7 @@ pub struct Item { pub name: Option, pub attrs: Attributes, pub inner: ItemEnum, - pub visibility: Option, + pub visibility: Visibility, pub def_id: DefId, pub stability: Option, pub deprecation: Option, @@ -2311,7 +2311,7 @@ impl Clean for hir::TraitItem { attrs: self.attrs.clean(cx), source: self.span.clean(cx), def_id: local_did, - visibility: None, + visibility: Visibility::Inherited, stability: get_stability(cx, local_did), deprecation: get_deprecation(cx, local_did), inner, @@ -2496,7 +2496,7 @@ impl Clean for ty::AssocItem { let visibility = match self.container { ty::ImplContainer(_) => self.vis.clean(cx), - ty::TraitContainer(_) => None, + ty::TraitContainer(_) => Inherited, }; Item { @@ -3293,9 +3293,9 @@ pub enum Visibility { Restricted(DefId, Path), } -impl Clean> for hir::Visibility { - fn clean(&self, cx: &DocContext<'_>) -> Option { - Some(match self.node { +impl Clean for hir::Visibility { + fn clean(&self, cx: &DocContext<'_>) -> Visibility { + match self.node { hir::VisibilityKind::Public => Visibility::Public, hir::VisibilityKind::Inherited => Visibility::Inherited, hir::VisibilityKind::Crate(_) => Visibility::Crate, @@ -3304,13 +3304,13 @@ impl Clean> for hir::Visibility { let did = register_res(cx, path.res); Visibility::Restricted(did, path) } - }) + } } } -impl Clean> for ty::Visibility { - fn clean(&self, _: &DocContext<'_>) -> Option { - Some(if *self == ty::Visibility::Public { Public } else { Inherited }) +impl Clean for ty::Visibility { + fn clean(&self, _: &DocContext<'_>) -> Visibility { + if *self == ty::Visibility::Public { Public } else { Inherited } } } @@ -3427,7 +3427,7 @@ impl Clean for doctree::Variant<'_> { name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), source: self.whence.clean(cx), - visibility: None, + visibility: Inherited, stability: cx.stability(self.id).clean(cx), deprecation: cx.deprecation(self.id).clean(cx), def_id: cx.tcx.hir().local_def_id(self.id), @@ -3470,7 +3470,7 @@ impl Clean for ty::VariantDef { name: Some(self.ident.clean(cx)), attrs: inline::load_attrs(cx, self.def_id).clean(cx), source: cx.tcx.def_span(self.def_id).clean(cx), - visibility: Some(Inherited), + visibility: Inherited, def_id: self.def_id, inner: VariantItem(Variant { kind }), stability: get_stability(cx, self.def_id), @@ -4333,7 +4333,7 @@ impl Clean for doctree::Macro<'_> { name: Some(name.clone()), attrs: self.attrs.clean(cx), source: self.whence.clean(cx), - visibility: Some(Public), + visibility: Public, stability: cx.stability(self.hid).clean(cx), deprecation: cx.deprecation(self.hid).clean(cx), def_id: self.def_id, @@ -4361,7 +4361,7 @@ impl Clean for doctree::ProcMacro<'_> { name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), source: self.whence.clean(cx), - visibility: Some(Public), + visibility: Public, stability: cx.stability(self.id).clean(cx), deprecation: cx.deprecation(self.id).clean(cx), def_id: cx.tcx.hir().local_def_id(self.id), diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 9baa69d981b52..3c62977bd77d3 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -111,7 +111,7 @@ impl Buffer { /// Helper to render an optional visibility with a space after it (if the /// visibility is preset) #[derive(Copy, Clone)] -pub struct VisSpace<'a>(pub &'a Option); +pub struct VisSpace<'a>(pub &'a clean::Visibility); /// Similarly to VisSpace, this structure is used to render a function style with a /// space after it. #[derive(Copy, Clone)] @@ -1034,11 +1034,7 @@ impl Function<'_> { impl<'a> fmt::Display for VisSpace<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Some(v) = self.0 { - fmt::Display::fmt(&v.print_with_space(), f) - } else { - Ok(()) - } + fmt::Display::fmt(&self.0.print_with_space(), f) } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 7aaf04f34d32f..32fa2daa026f7 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1511,7 +1511,7 @@ impl DocFolder for Cache { self.paths.insert(item.def_id, (stack, ItemType::Enum)); } - clean::PrimitiveItem(..) if item.visibility.is_some() => { + clean::PrimitiveItem(..) => { self.add_aliases(&item); self.paths.insert(item.def_id, (self.stack.clone(), item.type_())); @@ -4306,8 +4306,7 @@ fn get_methods( ) -> Vec { i.items.iter().filter_map(|item| { match item.name { - // Maybe check with clean::Visibility::Public as well? - Some(ref name) if !name.is_empty() && item.visibility.is_some() && item.is_method() => { + Some(ref name) if !name.is_empty() && item.is_method() => { if !for_deref || should_render_item(item, deref_mut) { Some(format!("{}", get_next_url(used_links, format!("method.{}", name)), diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index d0f2cdad8f3e4..f6560218a78c8 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -185,13 +185,13 @@ impl<'a> DocFolder for Stripper<'a> { } clean::StructFieldItem(..) => { - if i.visibility != Some(clean::Public) { + if i.visibility != clean::Public { return StripItem(i).strip(); } } clean::ModuleItem(..) => { - if i.def_id.is_local() && i.visibility != Some(clean::Public) { + if i.def_id.is_local() && i.visibility != clean::Public { debug!("Stripper: stripping module {:?}", i.name); let old = mem::replace(&mut self.update_retained, false); let ret = StripItem(self.fold_item_recur(i).unwrap()).strip(); @@ -299,7 +299,7 @@ impl DocFolder for ImportStripper { fn fold_item(&mut self, i: Item) -> Option { match i.inner { clean::ExternCrateItem(..) | clean::ImportItem(..) - if i.visibility != Some(clean::Public) => + if i.visibility != clean::Public => { None } From 8a9dab3a203ef26c6f8477bd388f2394747d598e Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 13 Sep 2019 08:36:00 -0400 Subject: [PATCH 019/413] Remove *Space wrappers in favor of direct impls or functions --- src/librustdoc/html/format.rs | 111 +++++++++++++--------------------- src/librustdoc/html/render.rs | 82 ++++++++++++------------- 2 files changed, 84 insertions(+), 109 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 3c62977bd77d3..fafd43cb60b69 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -108,28 +108,6 @@ impl Buffer { } } -/// Helper to render an optional visibility with a space after it (if the -/// visibility is preset) -#[derive(Copy, Clone)] -pub struct VisSpace<'a>(pub &'a clean::Visibility); -/// Similarly to VisSpace, this structure is used to render a function style with a -/// space after it. -#[derive(Copy, Clone)] -pub struct UnsafetySpace(pub hir::Unsafety); -/// Similarly to VisSpace, this structure is used to render a function constness -/// with a space after it. -#[derive(Copy, Clone)] -pub struct ConstnessSpace(pub hir::Constness); -/// Similarly to VisSpace, this structure is used to render a function asyncness -/// with a space after it. -#[derive(Copy, Clone)] -pub struct AsyncSpace(pub hir::IsAsync); -/// Similar to VisSpace, but used for mutability -#[derive(Copy, Clone)] -pub struct MutableSpace(pub clean::Mutability); -pub struct AbiSpace(pub Abi); -pub struct DefaultSpace(pub bool); - /// Wrapper struct for properly emitting a function or method declaration. pub struct Function<'a> { /// The declaration to emit. @@ -638,12 +616,13 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> clean::BareFunction(ref decl) => { if f.alternate() { write!(f, "{}{:#}fn{:#}{:#}", - UnsafetySpace(decl.unsafety), - AbiSpace(decl.abi), + decl.unsafety.print_with_space(), + print_abi_with_space(decl.abi), decl.print_generic_params(), decl.decl.print()) } else { - write!(f, "{}{}", UnsafetySpace(decl.unsafety), AbiSpace(decl.abi))?; + write!(f, "{}{}", + decl.unsafety.print_with_space(), print_abi_with_space(decl.abi))?; primitive_link(f, PrimitiveType::Fn, "fn")?; write!(f, "{}{}", decl.print_generic_params(), decl.decl.print()) } @@ -705,7 +684,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter<'_>, use_absolute: bool) -> Some(l) => format!("{} ", l.print()), _ => String::new() }; - let m = MutableSpace(mutability); + let m = mutability.print_with_space(); let amp = if f.alternate() { "&".to_string() } else { @@ -956,13 +935,13 @@ impl Function<'_> { } clean::SelfBorrowed(Some(ref lt), mtbl) => { args.push_str( - &format!("{}{} {}self", amp, lt.print(), MutableSpace(mtbl))); + &format!("{}{} {}self", amp, lt.print(), mtbl.print_with_space())); args_plain.push_str( - &format!("&{} {}self", lt.print(), MutableSpace(mtbl))); + &format!("&{} {}self", lt.print(), mtbl.print_with_space())); } clean::SelfBorrowed(None, mtbl) => { - args.push_str(&format!("{}{}self", amp, MutableSpace(mtbl))); - args_plain.push_str(&format!("&{}self", MutableSpace(mtbl))); + args.push_str(&format!("{}{}self", amp, mtbl.print_with_space())); + args_plain.push_str(&format!("&{}self", mtbl.print_with_space())); } clean::SelfExplicit(ref typ) => { if f.alternate() { @@ -1032,14 +1011,8 @@ impl Function<'_> { } } -impl<'a> fmt::Display for VisSpace<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.0.print_with_space(), f) - } -} - impl clean::Visibility { - fn print_with_space(&self) -> impl fmt::Display + '_ { + crate fn print_with_space(&self) -> impl fmt::Display + '_ { display_fn(move |f| { match *self { clean::Public => f.write_str("pub "), @@ -1060,29 +1033,33 @@ impl clean::Visibility { } } -impl fmt::Display for UnsafetySpace { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 { - hir::Unsafety::Unsafe => write!(f, "unsafe "), - hir::Unsafety::Normal => Ok(()) +crate trait PrintWithSpace { + fn print_with_space(&self) -> &str; +} + +impl PrintWithSpace for hir::Unsafety { + fn print_with_space(&self) -> &str { + match self { + hir::Unsafety::Unsafe => "unsafe ", + hir::Unsafety::Normal => "" } } } -impl fmt::Display for ConstnessSpace { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 { - hir::Constness::Const => write!(f, "const "), - hir::Constness::NotConst => Ok(()) +impl PrintWithSpace for hir::Constness { + fn print_with_space(&self) -> &str { + match self { + hir::Constness::Const => "const ", + hir::Constness::NotConst => "" } } } -impl fmt::Display for AsyncSpace { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 { - hir::IsAsync::Async => write!(f, "async "), - hir::IsAsync::NotAsync => Ok(()), +impl PrintWithSpace for hir::IsAsync { + fn print_with_space(&self) -> &str { + match self { + hir::IsAsync::Async => "async ", + hir::IsAsync::NotAsync => "", } } } @@ -1156,32 +1133,30 @@ impl clean::TypeBinding { } } -impl fmt::Display for MutableSpace { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - MutableSpace(clean::Immutable) => Ok(()), - MutableSpace(clean::Mutable) => write!(f, "mut "), +impl clean::Mutability { + crate fn print_with_space(&self) -> &str { + match self { + clean::Immutable => "", + clean::Mutable => "mut ", } } } -impl fmt::Display for AbiSpace { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +crate fn print_abi_with_space(abi: Abi) -> impl fmt::Display { + display_fn(move |f| { let quot = if f.alternate() { "\"" } else { """ }; - match self.0 { + match abi { Abi::Rust => Ok(()), abi => write!(f, "extern {0}{1}{0} ", quot, abi.name()), } - } + }) } -impl fmt::Display for DefaultSpace { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.0 { - write!(f, "default ") - } else { - Ok(()) - } +crate fn print_default_space<'a>(v: bool) -> &'a str { + if v { + "default " + } else { + "" } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 32fa2daa026f7..0b3cf5ea1e226 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -65,9 +65,9 @@ use crate::docfs::{DocFS, ErrorStorage, PathError}; use crate::doctree; use crate::fold::DocFolder; use crate::html::escape::Escape; -use crate::html::format::{Buffer, AsyncSpace, ConstnessSpace}; -use crate::html::format::{print_generic_bounds, WhereClause, href, AbiSpace, DefaultSpace}; -use crate::html::format::{VisSpace, Function, UnsafetySpace, MutableSpace}; +use crate::html::format::{Buffer, PrintWithSpace, print_abi_with_space}; +use crate::html::format::{print_generic_bounds, WhereClause, href, print_default_space}; +use crate::html::format::{Function}; use crate::html::format::fmt_impl_for_trait_page; use crate::html::item_type::ItemType; use crate::html::markdown::{self, Markdown, MarkdownHtml, MarkdownSummaryLine, ErrorCodes, IdMap}; @@ -2573,13 +2573,13 @@ fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean: match *src { Some(ref src) => { write!(w, "{}extern crate {} as {};", - VisSpace(&myitem.visibility), + myitem.visibility.print_with_space(), anchor(myitem.def_id, src), name) } None => { write!(w, "{}extern crate {};", - VisSpace(&myitem.visibility), + myitem.visibility.print_with_space(), anchor(myitem.def_id, name)) } } @@ -2588,7 +2588,7 @@ fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean: clean::ImportItem(ref import) => { write!(w, "{}{}", - VisSpace(&myitem.visibility), import.print()); + myitem.visibility.print_with_space(), import.print()); } _ => { @@ -2794,7 +2794,7 @@ fn item_constant(w: &mut Buffer, cx: &Context, it: &clean::Item, c: &clean::Cons render_attributes(w, it, false); write!(w, "{vis}const \ {name}: {typ}", - vis = VisSpace(&it.visibility), + vis = it.visibility.print_with_space(), name = it.name.as_ref().unwrap(), typ = c.type_.print()); document(w, cx, it) @@ -2805,8 +2805,8 @@ fn item_static(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Static render_attributes(w, it, false); write!(w, "{vis}static {mutability}\ {name}: {typ}", - vis = VisSpace(&it.visibility), - mutability = MutableSpace(s.mutability), + vis = it.visibility.print_with_space(), + mutability = s.mutability.print_with_space(), name = it.name.as_ref().unwrap(), typ = s.type_.print()); document(w, cx, it) @@ -2815,11 +2815,11 @@ fn item_static(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Static fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Function) { let header_len = format!( "{}{}{}{}{:#}fn {}{:#}", - VisSpace(&it.visibility), - ConstnessSpace(f.header.constness), - UnsafetySpace(f.header.unsafety), - AsyncSpace(f.header.asyncness), - AbiSpace(f.header.abi), + it.visibility.print_with_space(), + f.header.constness.print_with_space(), + f.header.unsafety.print_with_space(), + f.header.asyncness.print_with_space(), + print_abi_with_space(f.header.abi), it.name.as_ref().unwrap(), f.generics.print() ).len(); @@ -2828,11 +2828,11 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func write!(w, "{vis}{constness}{unsafety}{asyncness}{abi}fn \ {name}{generics}{decl}{where_clause}", - vis = VisSpace(&it.visibility), - constness = ConstnessSpace(f.header.constness), - unsafety = UnsafetySpace(f.header.unsafety), - asyncness = AsyncSpace(f.header.asyncness), - abi = AbiSpace(f.header.abi), + vis = it.visibility.print_with_space(), + constness = f.header.constness.print_with_space(), + unsafety = f.header.unsafety.print_with_space(), + asyncness = f.header.asyncness.print_with_space(), + abi = print_abi_with_space(f.header.abi), name = it.name.as_ref().unwrap(), generics = f.generics.print(), where_clause = WhereClause { gens: &f.generics, indent: 0, end_newline: true }, @@ -2913,8 +2913,8 @@ fn item_trait( write!(w, "
    ");
             render_attributes(w, it, true);
             write!(w, "{}{}{}trait {}{}{}",
    -               VisSpace(&it.visibility),
    -               UnsafetySpace(t.unsafety),
    +               it.visibility.print_with_space(),
    +               t.unsafety.print_with_space(),
                    if t.is_auto { "auto " } else { "" },
                    it.name.as_ref().unwrap(),
                    t.generics.print(),
    @@ -3175,7 +3175,7 @@ fn assoc_const(w: &mut Buffer,
                    extra: &str) {
         write!(w, "{}{}const {}: {}",
                extra,
    -           VisSpace(&it.visibility),
    +           it.visibility.print_with_space(),
                naive_assoc_href(it, link),
                it.name.as_ref().unwrap(),
                ty.print());
    @@ -3240,12 +3240,12 @@ fn render_assoc_item(w: &mut Buffer,
             };
             let mut header_len = format!(
                 "{}{}{}{}{}{:#}fn {}{:#}",
    -            VisSpace(&meth.visibility),
    -            ConstnessSpace(header.constness),
    -            UnsafetySpace(header.unsafety),
    -            AsyncSpace(header.asyncness),
    -            DefaultSpace(meth.is_default()),
    -            AbiSpace(header.abi),
    +            meth.visibility.print_with_space(),
    +            header.constness.print_with_space(),
    +            header.unsafety.print_with_space(),
    +            header.asyncness.print_with_space(),
    +            print_default_space(meth.is_default()),
    +            print_abi_with_space(header.abi),
                 name,
                 g.print()
             ).len();
    @@ -3259,12 +3259,12 @@ fn render_assoc_item(w: &mut Buffer,
             write!(w, "{}{}{}{}{}{}{}fn {name}\
                        {generics}{decl}{where_clause}",
                    if parent == ItemType::Trait { "    " } else { "" },
    -               VisSpace(&meth.visibility),
    -               ConstnessSpace(header.constness),
    -               UnsafetySpace(header.unsafety),
    -               AsyncSpace(header.asyncness),
    -               DefaultSpace(meth.is_default()),
    -               AbiSpace(header.abi),
    +               meth.visibility.print_with_space(),
    +               header.constness.print_with_space(),
    +               header.unsafety.print_with_space(),
    +               header.asyncness.print_with_space(),
    +               print_default_space(meth.is_default()),
    +               print_abi_with_space(header.abi),
                    href = href,
                    name = name,
                    generics = g.print(),
    @@ -3399,7 +3399,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) {
             write!(w, "
    ");
             render_attributes(w, it, true);
             write!(w, "{}enum {}{}{}",
    -               VisSpace(&it.visibility),
    +               it.visibility.print_with_space(),
                    it.name.as_ref().unwrap(),
                    e.generics.print(),
                    WhereClause { gens: &e.generics, indent: 0, end_newline: true });
    @@ -3588,7 +3588,7 @@ fn render_struct(w: &mut Buffer, it: &clean::Item,
                      tab: &str,
                      structhead: bool) {
         write!(w, "{}{}{}",
    -           VisSpace(&it.visibility),
    +           it.visibility.print_with_space(),
                if structhead {"struct "} else {""},
                it.name.as_ref().unwrap());
         if let Some(g) = g {
    @@ -3605,7 +3605,7 @@ fn render_struct(w: &mut Buffer, it: &clean::Item,
                     if let clean::StructFieldItem(ref ty) = field.inner {
                         write!(w, "\n{}    {}{}: {},",
                                tab,
    -                           VisSpace(&field.visibility),
    +                           field.visibility.print_with_space(),
                                field.name.as_ref().unwrap(),
                                ty.print());
                         has_visible_fields = true;
    @@ -3635,7 +3635,7 @@ fn render_struct(w: &mut Buffer, it: &clean::Item,
                             write!(w, "_")
                         }
                         clean::StructFieldItem(ref ty) => {
    -                        write!(w, "{}{}", VisSpace(&field.visibility), ty.print())
    +                        write!(w, "{}{}", field.visibility.print_with_space(), ty.print())
                         }
                         _ => unreachable!()
                     }
    @@ -3662,7 +3662,7 @@ fn render_union(w: &mut Buffer, it: &clean::Item,
                     tab: &str,
                     structhead: bool) {
         write!(w, "{}{}{}",
    -           VisSpace(&it.visibility),
    +           it.visibility.print_with_space(),
                if structhead {"union "} else {""},
                it.name.as_ref().unwrap());
         if let Some(g) = g {
    @@ -3674,7 +3674,7 @@ fn render_union(w: &mut Buffer, it: &clean::Item,
         for field in fields {
             if let clean::StructFieldItem(ref ty) = field.inner {
                 write!(w, "    {}{}: {},\n{}",
    -                   VisSpace(&field.visibility),
    +                   field.visibility.print_with_space(),
                        field.name.as_ref().unwrap(),
                        ty.print(),
                        tab);
    @@ -4186,7 +4186,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context, it: &clean::Item) {
         write!(
             w,
             "    {}type {};\n}}
    ", - VisSpace(&it.visibility), + it.visibility.print_with_space(), it.name.as_ref().unwrap(), ); From 3f144e119ec958b2a6ac3db3568b1bd2b3ba488a Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 13 Sep 2019 08:41:27 -0400 Subject: [PATCH 020/413] Move Toc printing from fmt::Display --- src/librustdoc/html/markdown.rs | 2 +- src/librustdoc/html/toc.rs | 37 ++++++++++++++------------------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 1a4fa38ff8db0..9ff1e1d31197d 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -752,7 +752,7 @@ impl MarkdownWithToc<'_> { html::push_html(&mut s, p); } - format!("{}", toc.into_toc(), s) + format!("{}", toc.into_toc().print(), s) } } diff --git a/src/librustdoc/html/toc.rs b/src/librustdoc/html/toc.rs index 2da7aceae8bf4..0fb2f8dd7962a 100644 --- a/src/librustdoc/html/toc.rs +++ b/src/librustdoc/html/toc.rs @@ -1,10 +1,7 @@ //! Table-of-contents creation. -use std::fmt; -use std::string::String; - /// A (recursive) table of contents -#[derive(PartialEq)] +#[derive(Debug, PartialEq)] pub struct Toc { /// The levels are strictly decreasing, i.e. /// @@ -28,7 +25,7 @@ impl Toc { } } -#[derive(PartialEq)] +#[derive(Debug, PartialEq)] pub struct TocEntry { level: u32, sec_number: String, @@ -165,25 +162,23 @@ impl TocBuilder { } } -impl fmt::Debug for Toc { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - -impl fmt::Display for Toc { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(fmt, "
      ")?; +impl Toc { + fn print_inner(&self, v: &mut String) { + v.push_str("
        "); for entry in &self.entries { - // recursively format this table of contents (the - // `{children}` is the key). - write!(fmt, - "\n
      • {num} {name}{children}
      • ", + // recursively format this table of contents + v.push_str(&format!("\n
      • {num} {name}", id = entry.id, - num = entry.sec_number, name = entry.name, - children = entry.children)? + num = entry.sec_number, name = entry.name)); + entry.children.print_inner(&mut *v); + v.push_str("
      • "); } - write!(fmt, "
      ") + v.push_str("
    "); + } + crate fn print(&self) -> String { + let mut v = String::new(); + self.print_inner(&mut v); + v } } From aa4055cd6c92095c1996dd6eb31b08cced604e88 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 13 Sep 2019 08:42:58 -0400 Subject: [PATCH 021/413] Simplify render_spotlight_traits --- src/librustdoc/html/render.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 0b3cf5ea1e226..8d5bd0d2e16e1 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3858,19 +3858,15 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool { } fn render_spotlight_traits(item: &clean::Item) -> String { - let mut out = String::new(); - match item.inner { clean::FunctionItem(clean::Function { ref decl, .. }) | clean::TyMethodItem(clean::TyMethod { ref decl, .. }) | clean::MethodItem(clean::Method { ref decl, .. }) | clean::ForeignFunctionItem(clean::Function { ref decl, .. }) => { - out = spotlight_decl(decl); + spotlight_decl(decl) } - _ => {} + _ => String::new() } - - out } fn spotlight_decl(decl: &clean::FnDecl) -> String { From e0e0c3787ca64d8c2540d703ca1e2f26607c5717 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 13 Sep 2019 09:26:11 -0400 Subject: [PATCH 022/413] Replace SlashChecker with ensure_trailing_slash --- src/librustdoc/html/layout.rs | 4 ++-- src/librustdoc/html/render.rs | 22 ++++++++++------------ 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 56074f4ab1192..6414241727a72 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -1,7 +1,7 @@ use std::path::PathBuf; use crate::externalfiles::ExternalHtml; -use crate::html::render::SlashChecker; +use crate::html::render::ensure_trailing_slash; use crate::html::format::{Buffer, Print}; #[derive(Clone)] @@ -180,7 +180,7 @@ pub fn render( css_class = page.css_class, logo = { let p = format!("{}{}", page.root_path, layout.krate); - let p = SlashChecker(&p); + let p = ensure_trailing_slash(&p); if layout.logo.is_empty() { format!("\
    \ diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 8d5bd0d2e16e1..9064dc8b44db4 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -33,7 +33,7 @@ use std::cmp::Ordering; use std::collections::{BTreeMap, VecDeque}; use std::default::Default; use std::error; -use std::fmt::{self, Display, Formatter, Write as FmtWrite}; +use std::fmt::{self, Formatter, Write as FmtWrite}; use std::ffi::OsStr; use std::fs::{self, File}; use std::io::prelude::*; @@ -82,16 +82,14 @@ mod tests; /// A pair of name and its optional document. pub type NameDoc = (String, Option); -pub struct SlashChecker<'a>(pub &'a str); - -impl<'a> Display for SlashChecker<'a> { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - if !self.0.ends_with("/") && !self.0.is_empty() { - write!(f, "{}/", self.0) +crate fn ensure_trailing_slash(v: &str) -> impl fmt::Display + '_ { + crate::html::format::display_fn(move |f| { + if !v.ends_with("/") && !v.is_empty() { + write!(f, "{}/", v) } else { - write!(f, "{}", self.0) + write!(f, "{}", v) } - } + }) } #[derive(Debug)] @@ -106,7 +104,7 @@ impl error::Error for Error { } } -impl Display for Error { +impl std::fmt::Display for Error { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let file = self.file.display().to_string(); if file.is_empty() { @@ -1162,7 +1160,7 @@ themePicker.onblur = handleThemeButtonsBlur; .iter() .map(|s| { format!("
  • {}
  • ", - SlashChecker(s), s) + ensure_trailing_slash(s), s) }) .collect::()); let v = layout::render(&cx.shared.layout, @@ -2286,7 +2284,7 @@ fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer) { fn item_path(ty: ItemType, name: &str) -> String { match ty { - ItemType::Module => format!("{}index.html", SlashChecker(name)), + ItemType::Module => format!("{}index.html", ensure_trailing_slash(name)), _ => format!("{}.{}.html", ty, name), } } From 98c94f6f771c0e3894a65e82572c5dca1c43167d Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 13 Sep 2019 09:51:32 -0400 Subject: [PATCH 023/413] Move edition field out of Context --- src/librustdoc/html/render.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 9064dc8b44db4..1ecb2293fc22c 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -164,8 +164,6 @@ struct Context { /// publicly reused items to redirect to the right location. pub render_redirect_pages: bool, pub codes: ErrorCodes, - /// The default edition used to parse doctests. - pub edition: Edition, /// The map used to ensure all generated 'id=' attributes are unique. id_map: Rc>, pub shared: Arc, @@ -208,6 +206,8 @@ crate struct SharedContext { pub generate_redirect_pages: bool, /// The fs handle we are working with. pub fs: DocFS, + /// The default edition used to parse doctests. + pub edition: Edition, } impl SharedContext { @@ -539,6 +539,7 @@ pub fn run(mut krate: clean::Crate, static_root_path, generate_redirect_pages, fs: DocFS::new(&errors), + edition, }; // If user passed in `--playground-url` arg, we fill in crate name here @@ -585,7 +586,6 @@ pub fn run(mut krate: clean::Crate, dst, render_redirect_pages: false, codes: ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()), - edition, id_map: Rc::new(RefCell::new(id_map)), shared: Arc::new(scx), playground, @@ -1134,7 +1134,7 @@ themePicker.onblur = handleThemeButtonsBlur; md_opts.output = cx.dst.clone(); md_opts.external_html = (*cx.shared).layout.external_html.clone(); - crate::markdown::render(index_page, md_opts, diag, cx.edition); + crate::markdown::render(index_page, md_opts, diag, cx.shared.edition); } else { let dst = cx.dst.join("index.html"); let page = layout::Page { @@ -2353,7 +2353,7 @@ fn render_markdown( if is_hidden { " hidden" } else { "" }, prefix, Markdown(md_text, &links, &mut ids, - cx.codes, cx.edition, &cx.playground).to_string()) + cx.codes, cx.shared.edition, &cx.playground).to_string()) } fn document_short( @@ -2710,7 +2710,8 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { if let Some(note) = note { let mut ids = cx.id_map.borrow_mut(); - let html = MarkdownHtml(¬e, &mut ids, error_codes, cx.edition, &cx.playground); + let html = MarkdownHtml( + ¬e, &mut ids, error_codes, cx.shared.edition, &cx.playground); message.push_str(&format!(": {}", html.to_string())); } stability.push(format!("
    {}
    ", message)); @@ -2763,7 +2764,7 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { &unstable_reason, &mut ids, error_codes, - cx.edition, + cx.shared.edition, &cx.playground, ).to_string() ); @@ -3960,7 +3961,7 @@ fn render_impl(w: &mut Buffer, cx: &Context, i: &Impl, link: AssocItemLink<'_>, let mut ids = cx.id_map.borrow_mut(); write!(w, "
    {}
    ", Markdown(&*dox, &i.impl_item.links(), &mut ids, - cx.codes, cx.edition, &cx.playground).to_string()); + cx.codes, cx.shared.edition, &cx.playground).to_string()); } } From c26518086eed253924f2f9b91f2dd812084e4b31 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 13 Sep 2019 10:34:04 -0400 Subject: [PATCH 024/413] Move error codes to shared context --- src/librustdoc/html/render.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 1ecb2293fc22c..fb751041644ee 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -163,7 +163,6 @@ struct Context { /// real location of an item. This is used to allow external links to /// publicly reused items to redirect to the right location. pub render_redirect_pages: bool, - pub codes: ErrorCodes, /// The map used to ensure all generated 'id=' attributes are unique. id_map: Rc>, pub shared: Arc, @@ -208,6 +207,7 @@ crate struct SharedContext { pub fs: DocFS, /// The default edition used to parse doctests. pub edition: Edition, + pub codes: ErrorCodes, } impl SharedContext { @@ -540,6 +540,7 @@ pub fn run(mut krate: clean::Crate, generate_redirect_pages, fs: DocFS::new(&errors), edition, + codes: ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()), }; // If user passed in `--playground-url` arg, we fill in crate name here @@ -585,7 +586,6 @@ pub fn run(mut krate: clean::Crate, current: Vec::new(), dst, render_redirect_pages: false, - codes: ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()), id_map: Rc::new(RefCell::new(id_map)), shared: Arc::new(scx), playground, @@ -2353,7 +2353,7 @@ fn render_markdown( if is_hidden { " hidden" } else { "" }, prefix, Markdown(md_text, &links, &mut ids, - cx.codes, cx.shared.edition, &cx.playground).to_string()) + cx.shared.codes, cx.shared.edition, &cx.playground).to_string()) } fn document_short( @@ -3961,7 +3961,7 @@ fn render_impl(w: &mut Buffer, cx: &Context, i: &Impl, link: AssocItemLink<'_>, let mut ids = cx.id_map.borrow_mut(); write!(w, "
    {}
    ", Markdown(&*dox, &i.impl_item.links(), &mut ids, - cx.codes, cx.shared.edition, &cx.playground).to_string()); + cx.shared.codes, cx.shared.edition, &cx.playground).to_string()); } } From f4bb5a7c1a3183f1af14695a48258331b0360860 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 13 Sep 2019 10:40:22 -0400 Subject: [PATCH 025/413] Move playground to shared context --- src/librustdoc/html/render.rs | 73 ++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index fb751041644ee..9d5cddd6d47a7 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -166,7 +166,6 @@ struct Context { /// The map used to ensure all generated 'id=' attributes are unique. id_map: Rc>, pub shared: Arc, - playground: Option, } crate struct SharedContext { @@ -208,6 +207,7 @@ crate struct SharedContext { /// The default edition used to parse doctests. pub edition: Edition, pub codes: ErrorCodes, + playground: Option, } impl SharedContext { @@ -518,31 +518,6 @@ pub fn run(mut krate: clean::Crate, _ => PathBuf::new(), }; let mut errors = Arc::new(ErrorStorage::new()); - let mut scx = SharedContext { - collapsed: krate.collapsed, - src_root, - include_sources: true, - local_sources: Default::default(), - issue_tracker_base_url: None, - layout: layout::Layout { - logo: String::new(), - favicon: String::new(), - external_html, - krate: krate.name.clone(), - css_file_extension: extension_css, - generate_search_filter, - }, - created_dirs: Default::default(), - sort_modules_alphabetically, - themes, - resource_suffix, - static_root_path, - generate_redirect_pages, - fs: DocFS::new(&errors), - edition, - codes: ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()), - }; - // If user passed in `--playground-url` arg, we fill in crate name here let mut playground = None; if let Some(url) = playground_url { @@ -551,6 +526,16 @@ pub fn run(mut krate: clean::Crate, url, }); } + let mut layout = layout::Layout { + logo: String::new(), + favicon: String::new(), + external_html, + krate: krate.name.clone(), + css_file_extension: extension_css, + generate_search_filter, + }; + let mut issue_tracker_base_url = None; + let mut include_sources = true; // Crawl the crate attributes looking for attributes which control how we're // going to emit HTML @@ -558,10 +543,10 @@ pub fn run(mut krate: clean::Crate, for attr in attrs.lists(sym::doc) { match (attr.name_or_empty(), attr.value_str()) { (sym::html_favicon_url, Some(s)) => { - scx.layout.favicon = s.to_string(); + layout.favicon = s.to_string(); } (sym::html_logo_url, Some(s)) => { - scx.layout.logo = s.to_string(); + layout.logo = s.to_string(); } (sym::html_playground_url, Some(s)) => { playground = Some(markdown::Playground { @@ -570,15 +555,34 @@ pub fn run(mut krate: clean::Crate, }); } (sym::issue_tracker_base_url, Some(s)) => { - scx.issue_tracker_base_url = Some(s.to_string()); + issue_tracker_base_url = Some(s.to_string()); } (sym::html_no_source, None) if attr.is_word() => { - scx.include_sources = false; + include_sources = false; } _ => {} } } } + let mut scx = SharedContext { + collapsed: krate.collapsed, + src_root, + include_sources, + local_sources: Default::default(), + issue_tracker_base_url, + layout, + created_dirs: Default::default(), + sort_modules_alphabetically, + themes, + resource_suffix, + static_root_path, + generate_redirect_pages, + fs: DocFS::new(&errors), + edition, + codes: ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()), + playground, + }; + let dst = output; scx.ensure_dir(&dst)?; krate = sources::render(&dst, &mut scx, krate)?; @@ -588,7 +592,6 @@ pub fn run(mut krate: clean::Crate, render_redirect_pages: false, id_map: Rc::new(RefCell::new(id_map)), shared: Arc::new(scx), - playground, }; // Crawl the crate to build various caches used for the output @@ -2353,7 +2356,7 @@ fn render_markdown( if is_hidden { " hidden" } else { "" }, prefix, Markdown(md_text, &links, &mut ids, - cx.shared.codes, cx.shared.edition, &cx.playground).to_string()) + cx.shared.codes, cx.shared.edition, &cx.shared.playground).to_string()) } fn document_short( @@ -2711,7 +2714,7 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { if let Some(note) = note { let mut ids = cx.id_map.borrow_mut(); let html = MarkdownHtml( - ¬e, &mut ids, error_codes, cx.shared.edition, &cx.playground); + ¬e, &mut ids, error_codes, cx.shared.edition, &cx.shared.playground); message.push_str(&format!(": {}", html.to_string())); } stability.push(format!("
    {}
    ", message)); @@ -2765,7 +2768,7 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { &mut ids, error_codes, cx.shared.edition, - &cx.playground, + &cx.shared.playground, ).to_string() ); } @@ -3961,7 +3964,7 @@ fn render_impl(w: &mut Buffer, cx: &Context, i: &Impl, link: AssocItemLink<'_>, let mut ids = cx.id_map.borrow_mut(); write!(w, "
    {}
    ", Markdown(&*dox, &i.impl_item.links(), &mut ids, - cx.shared.codes, cx.shared.edition, &cx.playground).to_string()); + cx.shared.codes, cx.shared.edition, &cx.shared.playground).to_string()); } } From f5ed0fd1c0175679c7f72ee0e6f8f5532f94a69f Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 13 Sep 2019 11:22:12 -0400 Subject: [PATCH 026/413] Move `Cache` generation to separate module --- src/librustdoc/html/render.rs | 668 +-------------------------- src/librustdoc/html/render/cache.rs | 675 ++++++++++++++++++++++++++++ 2 files changed, 689 insertions(+), 654 deletions(-) create mode 100644 src/librustdoc/html/render/cache.rs diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 9d5cddd6d47a7..ff7134ab7c0d5 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -25,8 +25,6 @@ //! These threads are not parallelized (they haven't been a bottleneck yet), and //! both occur before the crate is rendered. -pub use self::ExternalLocation::*; - use std::borrow::Cow; use std::cell::{Cell, RefCell}; use std::cmp::Ordering; @@ -38,7 +36,6 @@ use std::ffi::OsStr; use std::fs::{self, File}; use std::io::prelude::*; use std::io::{self, BufReader}; -use std::mem; use std::path::{PathBuf, Path, Component}; use std::str; use std::sync::Arc; @@ -52,7 +49,7 @@ use syntax::ext::base::MacroKind; use syntax::source_map::FileName; use syntax::feature_gate::UnstableFeatures; use syntax::symbol::{Symbol, sym}; -use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; +use rustc::hir::def_id::DefId; use rustc::middle::privacy::AccessLevels; use rustc::middle::stability; use rustc::hir; @@ -63,7 +60,6 @@ use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy, Mutabilit use crate::config::RenderOptions; use crate::docfs::{DocFS, ErrorStorage, PathError}; use crate::doctree; -use crate::fold::DocFolder; use crate::html::escape::Escape; use crate::html::format::{Buffer, PrintWithSpace, print_abi_with_space}; use crate::html::format::{print_generic_bounds, WhereClause, href, print_default_space}; @@ -79,6 +75,11 @@ use minifier; #[cfg(test)] mod tests; +mod cache; + +use cache::Cache; +crate use cache::ExternalLocation::{self, *}; + /// A pair of name and its optional document. pub type NameDoc = (String, Option); @@ -234,16 +235,6 @@ impl SharedContext { } } -/// Indicates where an external crate can be found. -pub enum ExternalLocation { - /// Remote URL root of the external crate - Remote(String), - /// This external crate can be found in the local doc/ folder - Local, - /// The external crate could not be found. - Unknown, -} - /// Metadata about implementations for a type or trait. #[derive(Clone, Debug)] pub struct Impl { @@ -263,106 +254,6 @@ impl Impl { } } -/// This cache is used to store information about the `clean::Crate` being -/// rendered in order to provide more useful documentation. This contains -/// information like all implementors of a trait, all traits a type implements, -/// documentation for all known traits, etc. -/// -/// This structure purposefully does not implement `Clone` because it's intended -/// to be a fairly large and expensive structure to clone. Instead this adheres -/// to `Send` so it may be stored in a `Arc` instance and shared among the various -/// rendering threads. -#[derive(Default)] -pub struct Cache { - /// Maps a type ID to all known implementations for that type. This is only - /// recognized for intra-crate `ResolvedPath` types, and is used to print - /// out extra documentation on the page of an enum/struct. - /// - /// The values of the map are a list of implementations and documentation - /// found on that implementation. - pub impls: FxHashMap>, - - /// Maintains a mapping of local crate `NodeId`s to the fully qualified name - /// and "short type description" of that node. This is used when generating - /// URLs when a type is being linked to. External paths are not located in - /// this map because the `External` type itself has all the information - /// necessary. - pub paths: FxHashMap, ItemType)>, - - /// Similar to `paths`, but only holds external paths. This is only used for - /// generating explicit hyperlinks to other crates. - pub external_paths: FxHashMap, ItemType)>, - - /// Maps local `DefId`s of exported types to fully qualified paths. - /// Unlike 'paths', this mapping ignores any renames that occur - /// due to 'use' statements. - /// - /// This map is used when writing out the special 'implementors' - /// javascript file. By using the exact path that the type - /// is declared with, we ensure that each path will be identical - /// to the path used if the corresponding type is inlined. By - /// doing this, we can detect duplicate impls on a trait page, and only display - /// the impl for the inlined type. - pub exact_paths: FxHashMap>, - - /// This map contains information about all known traits of this crate. - /// Implementations of a crate should inherit the documentation of the - /// parent trait if no extra documentation is specified, and default methods - /// should show up in documentation about trait implementations. - pub traits: FxHashMap, - - /// When rendering traits, it's often useful to be able to list all - /// implementors of the trait, and this mapping is exactly, that: a mapping - /// of trait ids to the list of known implementors of the trait - pub implementors: FxHashMap>, - - /// Cache of where external crate documentation can be found. - pub extern_locations: FxHashMap, - - /// Cache of where documentation for primitives can be found. - pub primitive_locations: FxHashMap, - - // Note that external items for which `doc(hidden)` applies to are shown as - // non-reachable while local items aren't. This is because we're reusing - // the access levels from the privacy check pass. - pub access_levels: AccessLevels, - - /// The version of the crate being documented, if given from the `--crate-version` flag. - pub crate_version: Option, - - // Private fields only used when initially crawling a crate to build a cache - - stack: Vec, - parent_stack: Vec, - parent_is_trait_impl: bool, - search_index: Vec, - stripped_mod: bool, - deref_trait_did: Option, - deref_mut_trait_did: Option, - owned_box_did: Option, - masked_crates: FxHashSet, - - // In rare case where a structure is defined in one module but implemented - // in another, if the implementing module is parsed before defining module, - // then the fully qualified name of the structure isn't presented in `paths` - // yet when its implementation methods are being indexed. Caches such methods - // and their parent id here and indexes them at the end of crate parsing. - orphan_impl_items: Vec<(DefId, clean::Item)>, - - // Similarly to `orphan_impl_items`, sometimes trait impls are picked up - // even though the trait itself is not exported. This can happen if a trait - // was defined in function/expression scope, since the impl will be picked - // up by `collect-trait-impls` but the trait won't be scraped out in the HIR - // crawl. In order to prevent crashes when looking for spotlight traits or - // when gathering trait documentation on a type, hold impls here while - // folding and add them to the cache later on if we find the trait. - orphan_trait_impls: Vec<(DefId, FxHashSet, Impl)>, - - /// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias, - /// we need the alias element to have an array of items. - aliases: FxHashMap>, -} - /// Temporary storage for data obtained during `RustdocVisitor::clean()`. /// Later on moved into `CACHE_KEY`. #[derive(Default)] @@ -594,89 +485,13 @@ pub fn run(mut krate: clean::Crate, shared: Arc::new(scx), }; - // Crawl the crate to build various caches used for the output - let RenderInfo { - inlined: _, - external_paths, - exact_paths, - access_levels, - deref_trait_did, - deref_mut_trait_did, - owned_box_did, - } = renderinfo; - - let external_paths = external_paths.into_iter() - .map(|(k, (v, t))| (k, (v, ItemType::from(t)))) - .collect(); - - let mut cache = Cache { - impls: Default::default(), - external_paths, - exact_paths, - paths: Default::default(), - implementors: Default::default(), - stack: Vec::new(), - parent_stack: Vec::new(), - search_index: Vec::new(), - parent_is_trait_impl: false, - extern_locations: Default::default(), - primitive_locations: Default::default(), - stripped_mod: false, - access_levels, - crate_version: krate.version.take(), - orphan_impl_items: Vec::new(), - orphan_trait_impls: Vec::new(), - traits: krate.external_traits.replace(Default::default()), - deref_trait_did, - deref_mut_trait_did, - owned_box_did, - masked_crates: mem::take(&mut krate.masked_crates), - aliases: Default::default(), - }; - - // Cache where all our extern crates are located - for &(n, ref e) in &krate.externs { - let src_root = match e.src { - FileName::Real(ref p) => match p.parent() { - Some(p) => p.to_path_buf(), - None => PathBuf::new(), - }, - _ => PathBuf::new(), - }; - let extern_url = extern_html_root_urls.get(&e.name).map(|u| &**u); - cache.extern_locations.insert(n, (e.name.clone(), src_root, - extern_location(e, extern_url, &cx.dst))); - - let did = DefId { krate: n, index: CRATE_DEF_INDEX }; - cache.external_paths.insert(did, (vec![e.name.to_string()], ItemType::Module)); - } - - // Cache where all known primitives have their documentation located. - // - // Favor linking to as local extern as possible, so iterate all crates in - // reverse topological order. - for &(_, ref e) in krate.externs.iter().rev() { - for &(def_id, prim, _) in &e.primitives { - cache.primitive_locations.insert(prim, def_id); - } - } - for &(def_id, prim, _) in &krate.primitives { - cache.primitive_locations.insert(prim, def_id); - } - - cache.stack.push(krate.name.clone()); - krate = cache.fold_crate(krate); - - for (trait_did, dids, impl_) in cache.orphan_trait_impls.drain(..) { - if cache.traits.contains_key(&trait_did) { - for did in dids { - cache.impls.entry(did).or_insert(vec![]).push(impl_.clone()); - } - } - } - - // Build our search index - let index = build_index(&krate, &mut cache); + let (new_crate, index, cache) = Cache::from_krate( + renderinfo, + &extern_html_root_urls, + &cx.dst, + krate, + ); + krate = new_crate; // Freeze the cache now that the index has been built. Put an Arc into TLS // for future parallelization opportunities @@ -701,76 +516,6 @@ pub fn run(mut krate: clean::Crate, } } -/// Builds the search index from the collected metadata -fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { - let mut nodeid_to_pathid = FxHashMap::default(); - let mut crate_items = Vec::with_capacity(cache.search_index.len()); - let mut crate_paths = Vec::::new(); - - let Cache { ref mut search_index, - ref orphan_impl_items, - ref mut paths, .. } = *cache; - - // Attach all orphan items to the type's definition if the type - // has since been learned. - for &(did, ref item) in orphan_impl_items { - if let Some(&(ref fqp, _)) = paths.get(&did) { - search_index.push(IndexItem { - ty: item.type_(), - name: item.name.clone().unwrap(), - path: fqp[..fqp.len() - 1].join("::"), - desc: shorten(plain_summary_line(item.doc_value())), - parent: Some(did), - parent_idx: None, - search_type: get_index_search_type(&item), - }); - } - } - - // Reduce `NodeId` in paths into smaller sequential numbers, - // and prune the paths that do not appear in the index. - let mut lastpath = String::new(); - let mut lastpathid = 0usize; - - for item in search_index { - item.parent_idx = item.parent.map(|nodeid| { - if nodeid_to_pathid.contains_key(&nodeid) { - *nodeid_to_pathid.get(&nodeid).unwrap() - } else { - let pathid = lastpathid; - nodeid_to_pathid.insert(nodeid, pathid); - lastpathid += 1; - - let &(ref fqp, short) = paths.get(&nodeid).unwrap(); - crate_paths.push(((short as usize), fqp.last().unwrap().clone()).to_json()); - pathid - } - }); - - // Omit the parent path if it is same to that of the prior item. - if lastpath == item.path { - item.path.clear(); - } else { - lastpath = item.path.clone(); - } - crate_items.push(item.to_json()); - } - - let crate_doc = krate.module.as_ref().map(|module| { - shorten(plain_summary_line(module.doc_value())) - }).unwrap_or(String::new()); - - let mut crate_data = BTreeMap::new(); - crate_data.insert("doc".to_owned(), Json::String(crate_doc)); - crate_data.insert("i".to_owned(), Json::Array(crate_items)); - crate_data.insert("p".to_owned(), Json::Array(crate_paths)); - - // Collect the index into a string - format!("searchIndex[{}] = {};", - as_json(&krate.name), - Json::Object(crate_data)) -} - fn write_shared( cx: &Context, krate: &clean::Crate, @@ -1327,327 +1072,6 @@ fn minify_replacer( } } -/// Attempts to find where an external crate is located, given that we're -/// rendering in to the specified source destination. -fn extern_location(e: &clean::ExternalCrate, extern_url: Option<&str>, dst: &Path) - -> ExternalLocation -{ - // See if there's documentation generated into the local directory - let local_location = dst.join(&e.name); - if local_location.is_dir() { - return Local; - } - - if let Some(url) = extern_url { - let mut url = url.to_string(); - if !url.ends_with("/") { - url.push('/'); - } - return Remote(url); - } - - // Failing that, see if there's an attribute specifying where to find this - // external crate - e.attrs.lists(sym::doc) - .filter(|a| a.check_name(sym::html_root_url)) - .filter_map(|a| a.value_str()) - .map(|url| { - let mut url = url.to_string(); - if !url.ends_with("/") { - url.push('/') - } - Remote(url) - }).next().unwrap_or(Unknown) // Well, at least we tried. -} - -impl DocFolder for Cache { - fn fold_item(&mut self, item: clean::Item) -> Option { - if item.def_id.is_local() { - debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.def_id); - } - - // If this is a stripped module, - // we don't want it or its children in the search index. - let orig_stripped_mod = match item.inner { - clean::StrippedItem(box clean::ModuleItem(..)) => { - mem::replace(&mut self.stripped_mod, true) - } - _ => self.stripped_mod, - }; - - // If the impl is from a masked crate or references something from a - // masked crate then remove it completely. - if let clean::ImplItem(ref i) = item.inner { - if self.masked_crates.contains(&item.def_id.krate) || - i.trait_.def_id().map_or(false, |d| self.masked_crates.contains(&d.krate)) || - i.for_.def_id().map_or(false, |d| self.masked_crates.contains(&d.krate)) { - return None; - } - } - - // Propagate a trait method's documentation to all implementors of the - // trait. - if let clean::TraitItem(ref t) = item.inner { - self.traits.entry(item.def_id).or_insert_with(|| t.clone()); - } - - // Collect all the implementors of traits. - if let clean::ImplItem(ref i) = item.inner { - if let Some(did) = i.trait_.def_id() { - if i.blanket_impl.is_none() { - self.implementors.entry(did).or_default().push(Impl { - impl_item: item.clone(), - }); - } - } - } - - // Index this method for searching later on. - if let Some(ref s) = item.name { - let (parent, is_inherent_impl_item) = match item.inner { - clean::StrippedItem(..) => ((None, None), false), - clean::AssocConstItem(..) | - clean::TypedefItem(_, true) if self.parent_is_trait_impl => { - // skip associated items in trait impls - ((None, None), false) - } - clean::AssocTypeItem(..) | - clean::TyMethodItem(..) | - clean::StructFieldItem(..) | - clean::VariantItem(..) => { - ((Some(*self.parent_stack.last().unwrap()), - Some(&self.stack[..self.stack.len() - 1])), - false) - } - clean::MethodItem(..) | clean::AssocConstItem(..) => { - if self.parent_stack.is_empty() { - ((None, None), false) - } else { - let last = self.parent_stack.last().unwrap(); - let did = *last; - let path = match self.paths.get(&did) { - // The current stack not necessarily has correlation - // for where the type was defined. On the other - // hand, `paths` always has the right - // information if present. - Some(&(ref fqp, ItemType::Trait)) | - Some(&(ref fqp, ItemType::Struct)) | - Some(&(ref fqp, ItemType::Union)) | - Some(&(ref fqp, ItemType::Enum)) => - Some(&fqp[..fqp.len() - 1]), - Some(..) => Some(&*self.stack), - None => None - }; - ((Some(*last), path), true) - } - } - _ => ((None, Some(&*self.stack)), false) - }; - - match parent { - (parent, Some(path)) if is_inherent_impl_item || (!self.stripped_mod) => { - debug_assert!(!item.is_stripped()); - - // A crate has a module at its root, containing all items, - // which should not be indexed. The crate-item itself is - // inserted later on when serializing the search-index. - if item.def_id.index != CRATE_DEF_INDEX { - self.search_index.push(IndexItem { - ty: item.type_(), - name: s.to_string(), - path: path.join("::"), - desc: shorten(plain_summary_line(item.doc_value())), - parent, - parent_idx: None, - search_type: get_index_search_type(&item), - }); - } - } - (Some(parent), None) if is_inherent_impl_item => { - // We have a parent, but we don't know where they're - // defined yet. Wait for later to index this item. - self.orphan_impl_items.push((parent, item.clone())); - } - _ => {} - } - } - - // Keep track of the fully qualified path for this item. - let pushed = match item.name { - Some(ref n) if !n.is_empty() => { - self.stack.push(n.to_string()); - true - } - _ => false, - }; - - match item.inner { - clean::StructItem(..) | clean::EnumItem(..) | - clean::TypedefItem(..) | clean::TraitItem(..) | - clean::FunctionItem(..) | clean::ModuleItem(..) | - clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) | - clean::ConstantItem(..) | clean::StaticItem(..) | - clean::UnionItem(..) | clean::ForeignTypeItem | - clean::MacroItem(..) | clean::ProcMacroItem(..) - if !self.stripped_mod => { - // Re-exported items mean that the same id can show up twice - // in the rustdoc ast that we're looking at. We know, - // however, that a re-exported item doesn't show up in the - // `public_items` map, so we can skip inserting into the - // paths map if there was already an entry present and we're - // not a public item. - if !self.paths.contains_key(&item.def_id) || - self.access_levels.is_public(item.def_id) - { - self.paths.insert(item.def_id, - (self.stack.clone(), item.type_())); - } - self.add_aliases(&item); - } - // Link variants to their parent enum because pages aren't emitted - // for each variant. - clean::VariantItem(..) if !self.stripped_mod => { - let mut stack = self.stack.clone(); - stack.pop(); - self.paths.insert(item.def_id, (stack, ItemType::Enum)); - } - - clean::PrimitiveItem(..) => { - self.add_aliases(&item); - self.paths.insert(item.def_id, (self.stack.clone(), - item.type_())); - } - - _ => {} - } - - // Maintain the parent stack - let orig_parent_is_trait_impl = self.parent_is_trait_impl; - let parent_pushed = match item.inner { - clean::TraitItem(..) | clean::EnumItem(..) | clean::ForeignTypeItem | - clean::StructItem(..) | clean::UnionItem(..) => { - self.parent_stack.push(item.def_id); - self.parent_is_trait_impl = false; - true - } - clean::ImplItem(ref i) => { - self.parent_is_trait_impl = i.trait_.is_some(); - match i.for_ { - clean::ResolvedPath{ did, .. } => { - self.parent_stack.push(did); - true - } - ref t => { - let prim_did = t.primitive_type().and_then(|t| { - self.primitive_locations.get(&t).cloned() - }); - match prim_did { - Some(did) => { - self.parent_stack.push(did); - true - } - None => false, - } - } - } - } - _ => false - }; - - // Once we've recursively found all the generics, hoard off all the - // implementations elsewhere. - let ret = self.fold_item_recur(item).and_then(|item| { - if let clean::Item { inner: clean::ImplItem(_), .. } = item { - // Figure out the id of this impl. This may map to a - // primitive rather than always to a struct/enum. - // Note: matching twice to restrict the lifetime of the `i` borrow. - let mut dids = FxHashSet::default(); - if let clean::Item { inner: clean::ImplItem(ref i), .. } = item { - match i.for_ { - clean::ResolvedPath { did, .. } | - clean::BorrowedRef { - type_: box clean::ResolvedPath { did, .. }, .. - } => { - dids.insert(did); - } - ref t => { - let did = t.primitive_type().and_then(|t| { - self.primitive_locations.get(&t).cloned() - }); - - if let Some(did) = did { - dids.insert(did); - } - } - } - - if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) { - for bound in generics { - if let Some(did) = bound.def_id() { - dids.insert(did); - } - } - } - } else { - unreachable!() - }; - let impl_item = Impl { - impl_item: item, - }; - if impl_item.trait_did().map_or(true, |d| self.traits.contains_key(&d)) { - for did in dids { - self.impls.entry(did).or_insert(vec![]).push(impl_item.clone()); - } - } else { - let trait_did = impl_item.trait_did().unwrap(); - self.orphan_trait_impls.push((trait_did, dids, impl_item)); - } - None - } else { - Some(item) - } - }); - - if pushed { self.stack.pop().unwrap(); } - if parent_pushed { self.parent_stack.pop().unwrap(); } - self.stripped_mod = orig_stripped_mod; - self.parent_is_trait_impl = orig_parent_is_trait_impl; - ret - } -} - -impl Cache { - fn add_aliases(&mut self, item: &clean::Item) { - if item.def_id.index == CRATE_DEF_INDEX { - return - } - if let Some(ref item_name) = item.name { - let path = self.paths.get(&item.def_id) - .map(|p| p.0[..p.0.len() - 1].join("::")) - .unwrap_or("std".to_owned()); - for alias in item.attrs.lists(sym::doc) - .filter(|a| a.check_name(sym::alias)) - .filter_map(|a| a.value_str() - .map(|s| s.to_string().replace("\"", ""))) - .filter(|v| !v.is_empty()) - .collect::>() - .into_iter() { - self.aliases.entry(alias) - .or_insert(Vec::with_capacity(1)) - .push(IndexItem { - ty: item.type_(), - name: item_name.to_string(), - path: path.clone(), - desc: shorten(plain_summary_line(item.doc_value())), - parent: None, - parent_idx: None, - search_type: get_index_search_type(&item), - }); - } - } - } -} - #[derive(Debug, Eq, PartialEq, Hash)] struct ItemEntry { url: String, @@ -4805,37 +4229,6 @@ fn make_item_keywords(it: &clean::Item) -> String { format!("{}, {}", BASIC_KEYWORDS, it.name.as_ref().unwrap()) } -fn get_index_search_type(item: &clean::Item) -> Option { - let (all_types, ret_types) = match item.inner { - clean::FunctionItem(ref f) => (&f.all_types, &f.ret_types), - clean::MethodItem(ref m) => (&m.all_types, &m.ret_types), - clean::TyMethodItem(ref m) => (&m.all_types, &m.ret_types), - _ => return None, - }; - - let inputs = all_types.iter().map(|arg| { - get_index_type(&arg) - }).filter(|a| a.name.is_some()).collect(); - let output = ret_types.iter().map(|arg| { - get_index_type(&arg) - }).filter(|a| a.name.is_some()).collect::>(); - let output = if output.is_empty() { - None - } else { - Some(output) - }; - - Some(IndexItemFunctionType { inputs, output }) -} - -fn get_index_type(clean_type: &clean::Type) -> Type { - let t = Type { - name: get_index_type_name(clean_type, true).map(|s| s.to_ascii_lowercase()), - generics: get_generics(clean_type), - }; - t -} - /// Returns a list of all paths used in the type. /// This is used to help deduplicate imported impls /// for reexported types. If any of the contained @@ -4893,39 +4286,6 @@ fn collect_paths_for_type(first_ty: clean::Type) -> Vec { out } -fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option { - match *clean_type { - clean::ResolvedPath { ref path, .. } => { - let segments = &path.segments; - let path_segment = segments.into_iter().last().unwrap_or_else(|| panic!( - "get_index_type_name(clean_type: {:?}, accept_generic: {:?}) had length zero path", - clean_type, accept_generic - )); - Some(path_segment.name.clone()) - } - clean::Generic(ref s) if accept_generic => Some(s.clone()), - clean::Primitive(ref p) => Some(format!("{:?}", p)), - clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_, accept_generic), - // FIXME: add all from clean::Type. - _ => None - } -} - -fn get_generics(clean_type: &clean::Type) -> Option> { - clean_type.generics() - .and_then(|types| { - let r = types.iter() - .filter_map(|t| get_index_type_name(t, false)) - .map(|s| s.to_ascii_lowercase()) - .collect::>(); - if r.is_empty() { - None - } else { - Some(r) - } - }) -} - -pub fn cache() -> Arc { +crate fn cache() -> Arc { CACHE_KEY.with(|c| c.borrow().clone()) } diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs new file mode 100644 index 0000000000000..e9f0955c54126 --- /dev/null +++ b/src/librustdoc/html/render/cache.rs @@ -0,0 +1,675 @@ +use crate::clean::{self, GetDefId, AttributesExt}; +use crate::fold::DocFolder; +use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId}; +use rustc::middle::privacy::AccessLevels; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use std::mem; +use std::path::{Path, PathBuf}; +use std::collections::BTreeMap; +use syntax::source_map::FileName; +use syntax::symbol::sym; +use serialize::json::{ToJson, Json, as_json}; + +use super::{ItemType, IndexItem, IndexItemFunctionType, Impl, shorten, plain_summary_line}; +use super::{Type, RenderInfo}; + +/// Indicates where an external crate can be found. +pub enum ExternalLocation { + /// Remote URL root of the external crate + Remote(String), + /// This external crate can be found in the local doc/ folder + Local, + /// The external crate could not be found. + Unknown, +} + +/// This cache is used to store information about the `clean::Crate` being +/// rendered in order to provide more useful documentation. This contains +/// information like all implementors of a trait, all traits a type implements, +/// documentation for all known traits, etc. +/// +/// This structure purposefully does not implement `Clone` because it's intended +/// to be a fairly large and expensive structure to clone. Instead this adheres +/// to `Send` so it may be stored in a `Arc` instance and shared among the various +/// rendering threads. +#[derive(Default)] +crate struct Cache { + /// Maps a type ID to all known implementations for that type. This is only + /// recognized for intra-crate `ResolvedPath` types, and is used to print + /// out extra documentation on the page of an enum/struct. + /// + /// The values of the map are a list of implementations and documentation + /// found on that implementation. + pub impls: FxHashMap>, + + /// Maintains a mapping of local crate `NodeId`s to the fully qualified name + /// and "short type description" of that node. This is used when generating + /// URLs when a type is being linked to. External paths are not located in + /// this map because the `External` type itself has all the information + /// necessary. + pub paths: FxHashMap, ItemType)>, + + /// Similar to `paths`, but only holds external paths. This is only used for + /// generating explicit hyperlinks to other crates. + pub external_paths: FxHashMap, ItemType)>, + + /// Maps local `DefId`s of exported types to fully qualified paths. + /// Unlike 'paths', this mapping ignores any renames that occur + /// due to 'use' statements. + /// + /// This map is used when writing out the special 'implementors' + /// javascript file. By using the exact path that the type + /// is declared with, we ensure that each path will be identical + /// to the path used if the corresponding type is inlined. By + /// doing this, we can detect duplicate impls on a trait page, and only display + /// the impl for the inlined type. + pub exact_paths: FxHashMap>, + + /// This map contains information about all known traits of this crate. + /// Implementations of a crate should inherit the documentation of the + /// parent trait if no extra documentation is specified, and default methods + /// should show up in documentation about trait implementations. + pub traits: FxHashMap, + + /// When rendering traits, it's often useful to be able to list all + /// implementors of the trait, and this mapping is exactly, that: a mapping + /// of trait ids to the list of known implementors of the trait + pub implementors: FxHashMap>, + + /// Cache of where external crate documentation can be found. + pub extern_locations: FxHashMap, + + /// Cache of where documentation for primitives can be found. + pub primitive_locations: FxHashMap, + + // Note that external items for which `doc(hidden)` applies to are shown as + // non-reachable while local items aren't. This is because we're reusing + // the access levels from the privacy check pass. + pub access_levels: AccessLevels, + + /// The version of the crate being documented, if given from the `--crate-version` flag. + pub crate_version: Option, + + // Private fields only used when initially crawling a crate to build a cache + + stack: Vec, + parent_stack: Vec, + parent_is_trait_impl: bool, + search_index: Vec, + stripped_mod: bool, + pub deref_trait_did: Option, + pub deref_mut_trait_did: Option, + pub owned_box_did: Option, + masked_crates: FxHashSet, + + // In rare case where a structure is defined in one module but implemented + // in another, if the implementing module is parsed before defining module, + // then the fully qualified name of the structure isn't presented in `paths` + // yet when its implementation methods are being indexed. Caches such methods + // and their parent id here and indexes them at the end of crate parsing. + orphan_impl_items: Vec<(DefId, clean::Item)>, + + // Similarly to `orphan_impl_items`, sometimes trait impls are picked up + // even though the trait itself is not exported. This can happen if a trait + // was defined in function/expression scope, since the impl will be picked + // up by `collect-trait-impls` but the trait won't be scraped out in the HIR + // crawl. In order to prevent crashes when looking for spotlight traits or + // when gathering trait documentation on a type, hold impls here while + // folding and add them to the cache later on if we find the trait. + orphan_trait_impls: Vec<(DefId, FxHashSet, Impl)>, + + /// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias, + /// we need the alias element to have an array of items. + pub(super) aliases: FxHashMap>, +} + +impl Cache { + pub fn from_krate( + renderinfo: RenderInfo, + extern_html_root_urls: &BTreeMap, + dst: &Path, + mut krate: clean::Crate, + ) -> (clean::Crate, String, Cache) { + // Crawl the crate to build various caches used for the output + let RenderInfo { + inlined: _, + external_paths, + exact_paths, + access_levels, + deref_trait_did, + deref_mut_trait_did, + owned_box_did, + } = renderinfo; + + let external_paths = external_paths.into_iter() + .map(|(k, (v, t))| (k, (v, ItemType::from(t)))) + .collect(); + + let mut cache = Cache { + impls: Default::default(), + external_paths, + exact_paths, + paths: Default::default(), + implementors: Default::default(), + stack: Vec::new(), + parent_stack: Vec::new(), + search_index: Vec::new(), + parent_is_trait_impl: false, + extern_locations: Default::default(), + primitive_locations: Default::default(), + stripped_mod: false, + access_levels, + crate_version: krate.version.take(), + orphan_impl_items: Vec::new(), + orphan_trait_impls: Vec::new(), + traits: krate.external_traits.replace(Default::default()), + deref_trait_did, + deref_mut_trait_did, + owned_box_did, + masked_crates: mem::take(&mut krate.masked_crates), + aliases: Default::default(), + }; + + // Cache where all our extern crates are located + for &(n, ref e) in &krate.externs { + let src_root = match e.src { + FileName::Real(ref p) => match p.parent() { + Some(p) => p.to_path_buf(), + None => PathBuf::new(), + }, + _ => PathBuf::new(), + }; + let extern_url = extern_html_root_urls.get(&e.name).map(|u| &**u); + cache.extern_locations.insert(n, (e.name.clone(), src_root, + extern_location(e, extern_url, &dst))); + + let did = DefId { krate: n, index: CRATE_DEF_INDEX }; + cache.external_paths.insert(did, (vec![e.name.to_string()], ItemType::Module)); + } + + // Cache where all known primitives have their documentation located. + // + // Favor linking to as local extern as possible, so iterate all crates in + // reverse topological order. + for &(_, ref e) in krate.externs.iter().rev() { + for &(def_id, prim, _) in &e.primitives { + cache.primitive_locations.insert(prim, def_id); + } + } + for &(def_id, prim, _) in &krate.primitives { + cache.primitive_locations.insert(prim, def_id); + } + + cache.stack.push(krate.name.clone()); + krate = cache.fold_crate(krate); + + for (trait_did, dids, impl_) in cache.orphan_trait_impls.drain(..) { + if cache.traits.contains_key(&trait_did) { + for did in dids { + cache.impls.entry(did).or_insert(vec![]).push(impl_.clone()); + } + } + } + + // Build our search index + let index = build_index(&krate, &mut cache); + + (krate, index, cache) + } +} + +impl DocFolder for Cache { + fn fold_item(&mut self, item: clean::Item) -> Option { + if item.def_id.is_local() { + debug!("folding {} \"{:?}\", id {:?}", item.type_(), item.name, item.def_id); + } + + // If this is a stripped module, + // we don't want it or its children in the search index. + let orig_stripped_mod = match item.inner { + clean::StrippedItem(box clean::ModuleItem(..)) => { + mem::replace(&mut self.stripped_mod, true) + } + _ => self.stripped_mod, + }; + + // If the impl is from a masked crate or references something from a + // masked crate then remove it completely. + if let clean::ImplItem(ref i) = item.inner { + if self.masked_crates.contains(&item.def_id.krate) || + i.trait_.def_id().map_or(false, |d| self.masked_crates.contains(&d.krate)) || + i.for_.def_id().map_or(false, |d| self.masked_crates.contains(&d.krate)) { + return None; + } + } + + // Propagate a trait method's documentation to all implementors of the + // trait. + if let clean::TraitItem(ref t) = item.inner { + self.traits.entry(item.def_id).or_insert_with(|| t.clone()); + } + + // Collect all the implementors of traits. + if let clean::ImplItem(ref i) = item.inner { + if let Some(did) = i.trait_.def_id() { + if i.blanket_impl.is_none() { + self.implementors.entry(did).or_default().push(Impl { + impl_item: item.clone(), + }); + } + } + } + + // Index this method for searching later on. + if let Some(ref s) = item.name { + let (parent, is_inherent_impl_item) = match item.inner { + clean::StrippedItem(..) => ((None, None), false), + clean::AssocConstItem(..) | + clean::TypedefItem(_, true) if self.parent_is_trait_impl => { + // skip associated items in trait impls + ((None, None), false) + } + clean::AssocTypeItem(..) | + clean::TyMethodItem(..) | + clean::StructFieldItem(..) | + clean::VariantItem(..) => { + ((Some(*self.parent_stack.last().unwrap()), + Some(&self.stack[..self.stack.len() - 1])), + false) + } + clean::MethodItem(..) | clean::AssocConstItem(..) => { + if self.parent_stack.is_empty() { + ((None, None), false) + } else { + let last = self.parent_stack.last().unwrap(); + let did = *last; + let path = match self.paths.get(&did) { + // The current stack not necessarily has correlation + // for where the type was defined. On the other + // hand, `paths` always has the right + // information if present. + Some(&(ref fqp, ItemType::Trait)) | + Some(&(ref fqp, ItemType::Struct)) | + Some(&(ref fqp, ItemType::Union)) | + Some(&(ref fqp, ItemType::Enum)) => + Some(&fqp[..fqp.len() - 1]), + Some(..) => Some(&*self.stack), + None => None + }; + ((Some(*last), path), true) + } + } + _ => ((None, Some(&*self.stack)), false) + }; + + match parent { + (parent, Some(path)) if is_inherent_impl_item || (!self.stripped_mod) => { + debug_assert!(!item.is_stripped()); + + // A crate has a module at its root, containing all items, + // which should not be indexed. The crate-item itself is + // inserted later on when serializing the search-index. + if item.def_id.index != CRATE_DEF_INDEX { + self.search_index.push(IndexItem { + ty: item.type_(), + name: s.to_string(), + path: path.join("::"), + desc: shorten(plain_summary_line(item.doc_value())), + parent, + parent_idx: None, + search_type: get_index_search_type(&item), + }); + } + } + (Some(parent), None) if is_inherent_impl_item => { + // We have a parent, but we don't know where they're + // defined yet. Wait for later to index this item. + self.orphan_impl_items.push((parent, item.clone())); + } + _ => {} + } + } + + // Keep track of the fully qualified path for this item. + let pushed = match item.name { + Some(ref n) if !n.is_empty() => { + self.stack.push(n.to_string()); + true + } + _ => false, + }; + + match item.inner { + clean::StructItem(..) | clean::EnumItem(..) | + clean::TypedefItem(..) | clean::TraitItem(..) | + clean::FunctionItem(..) | clean::ModuleItem(..) | + clean::ForeignFunctionItem(..) | clean::ForeignStaticItem(..) | + clean::ConstantItem(..) | clean::StaticItem(..) | + clean::UnionItem(..) | clean::ForeignTypeItem | + clean::MacroItem(..) | clean::ProcMacroItem(..) + if !self.stripped_mod => { + // Re-exported items mean that the same id can show up twice + // in the rustdoc ast that we're looking at. We know, + // however, that a re-exported item doesn't show up in the + // `public_items` map, so we can skip inserting into the + // paths map if there was already an entry present and we're + // not a public item. + if !self.paths.contains_key(&item.def_id) || + self.access_levels.is_public(item.def_id) + { + self.paths.insert(item.def_id, + (self.stack.clone(), item.type_())); + } + self.add_aliases(&item); + } + // Link variants to their parent enum because pages aren't emitted + // for each variant. + clean::VariantItem(..) if !self.stripped_mod => { + let mut stack = self.stack.clone(); + stack.pop(); + self.paths.insert(item.def_id, (stack, ItemType::Enum)); + } + + clean::PrimitiveItem(..) => { + self.add_aliases(&item); + self.paths.insert(item.def_id, (self.stack.clone(), + item.type_())); + } + + _ => {} + } + + // Maintain the parent stack + let orig_parent_is_trait_impl = self.parent_is_trait_impl; + let parent_pushed = match item.inner { + clean::TraitItem(..) | clean::EnumItem(..) | clean::ForeignTypeItem | + clean::StructItem(..) | clean::UnionItem(..) => { + self.parent_stack.push(item.def_id); + self.parent_is_trait_impl = false; + true + } + clean::ImplItem(ref i) => { + self.parent_is_trait_impl = i.trait_.is_some(); + match i.for_ { + clean::ResolvedPath{ did, .. } => { + self.parent_stack.push(did); + true + } + ref t => { + let prim_did = t.primitive_type().and_then(|t| { + self.primitive_locations.get(&t).cloned() + }); + match prim_did { + Some(did) => { + self.parent_stack.push(did); + true + } + None => false, + } + } + } + } + _ => false + }; + + // Once we've recursively found all the generics, hoard off all the + // implementations elsewhere. + let ret = self.fold_item_recur(item).and_then(|item| { + if let clean::Item { inner: clean::ImplItem(_), .. } = item { + // Figure out the id of this impl. This may map to a + // primitive rather than always to a struct/enum. + // Note: matching twice to restrict the lifetime of the `i` borrow. + let mut dids = FxHashSet::default(); + if let clean::Item { inner: clean::ImplItem(ref i), .. } = item { + match i.for_ { + clean::ResolvedPath { did, .. } | + clean::BorrowedRef { + type_: box clean::ResolvedPath { did, .. }, .. + } => { + dids.insert(did); + } + ref t => { + let did = t.primitive_type().and_then(|t| { + self.primitive_locations.get(&t).cloned() + }); + + if let Some(did) = did { + dids.insert(did); + } + } + } + + if let Some(generics) = i.trait_.as_ref().and_then(|t| t.generics()) { + for bound in generics { + if let Some(did) = bound.def_id() { + dids.insert(did); + } + } + } + } else { + unreachable!() + }; + let impl_item = Impl { + impl_item: item, + }; + if impl_item.trait_did().map_or(true, |d| self.traits.contains_key(&d)) { + for did in dids { + self.impls.entry(did).or_insert(vec![]).push(impl_item.clone()); + } + } else { + let trait_did = impl_item.trait_did().unwrap(); + self.orphan_trait_impls.push((trait_did, dids, impl_item)); + } + None + } else { + Some(item) + } + }); + + if pushed { self.stack.pop().unwrap(); } + if parent_pushed { self.parent_stack.pop().unwrap(); } + self.stripped_mod = orig_stripped_mod; + self.parent_is_trait_impl = orig_parent_is_trait_impl; + ret + } +} + +impl Cache { + fn add_aliases(&mut self, item: &clean::Item) { + if item.def_id.index == CRATE_DEF_INDEX { + return + } + if let Some(ref item_name) = item.name { + let path = self.paths.get(&item.def_id) + .map(|p| p.0[..p.0.len() - 1].join("::")) + .unwrap_or("std".to_owned()); + for alias in item.attrs.lists(sym::doc) + .filter(|a| a.check_name(sym::alias)) + .filter_map(|a| a.value_str() + .map(|s| s.to_string().replace("\"", ""))) + .filter(|v| !v.is_empty()) + .collect::>() + .into_iter() { + self.aliases.entry(alias) + .or_insert(Vec::with_capacity(1)) + .push(IndexItem { + ty: item.type_(), + name: item_name.to_string(), + path: path.clone(), + desc: shorten(plain_summary_line(item.doc_value())), + parent: None, + parent_idx: None, + search_type: get_index_search_type(&item), + }); + } + } + } +} + +/// Attempts to find where an external crate is located, given that we're +/// rendering in to the specified source destination. +fn extern_location(e: &clean::ExternalCrate, extern_url: Option<&str>, dst: &Path) + -> ExternalLocation +{ + use ExternalLocation::*; + // See if there's documentation generated into the local directory + let local_location = dst.join(&e.name); + if local_location.is_dir() { + return Local; + } + + if let Some(url) = extern_url { + let mut url = url.to_string(); + if !url.ends_with("/") { + url.push('/'); + } + return Remote(url); + } + + // Failing that, see if there's an attribute specifying where to find this + // external crate + e.attrs.lists(sym::doc) + .filter(|a| a.check_name(sym::html_root_url)) + .filter_map(|a| a.value_str()) + .map(|url| { + let mut url = url.to_string(); + if !url.ends_with("/") { + url.push('/') + } + Remote(url) + }).next().unwrap_or(Unknown) // Well, at least we tried. +} + +/// Builds the search index from the collected metadata +fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { + let mut nodeid_to_pathid = FxHashMap::default(); + let mut crate_items = Vec::with_capacity(cache.search_index.len()); + let mut crate_paths = Vec::::new(); + + let Cache { ref mut search_index, + ref orphan_impl_items, + ref mut paths, .. } = *cache; + + // Attach all orphan items to the type's definition if the type + // has since been learned. + for &(did, ref item) in orphan_impl_items { + if let Some(&(ref fqp, _)) = paths.get(&did) { + search_index.push(IndexItem { + ty: item.type_(), + name: item.name.clone().unwrap(), + path: fqp[..fqp.len() - 1].join("::"), + desc: shorten(plain_summary_line(item.doc_value())), + parent: Some(did), + parent_idx: None, + search_type: get_index_search_type(&item), + }); + } + } + + // Reduce `NodeId` in paths into smaller sequential numbers, + // and prune the paths that do not appear in the index. + let mut lastpath = String::new(); + let mut lastpathid = 0usize; + + for item in search_index { + item.parent_idx = item.parent.map(|nodeid| { + if nodeid_to_pathid.contains_key(&nodeid) { + *nodeid_to_pathid.get(&nodeid).unwrap() + } else { + let pathid = lastpathid; + nodeid_to_pathid.insert(nodeid, pathid); + lastpathid += 1; + + let &(ref fqp, short) = paths.get(&nodeid).unwrap(); + crate_paths.push(((short as usize), fqp.last().unwrap().clone()).to_json()); + pathid + } + }); + + // Omit the parent path if it is same to that of the prior item. + if lastpath == item.path { + item.path.clear(); + } else { + lastpath = item.path.clone(); + } + crate_items.push(item.to_json()); + } + + let crate_doc = krate.module.as_ref().map(|module| { + shorten(plain_summary_line(module.doc_value())) + }).unwrap_or(String::new()); + + let mut crate_data = BTreeMap::new(); + crate_data.insert("doc".to_owned(), Json::String(crate_doc)); + crate_data.insert("i".to_owned(), Json::Array(crate_items)); + crate_data.insert("p".to_owned(), Json::Array(crate_paths)); + + // Collect the index into a string + format!("searchIndex[{}] = {};", + as_json(&krate.name), + Json::Object(crate_data)) +} + +fn get_index_search_type(item: &clean::Item) -> Option { + let (all_types, ret_types) = match item.inner { + clean::FunctionItem(ref f) => (&f.all_types, &f.ret_types), + clean::MethodItem(ref m) => (&m.all_types, &m.ret_types), + clean::TyMethodItem(ref m) => (&m.all_types, &m.ret_types), + _ => return None, + }; + + let inputs = all_types.iter().map(|arg| { + get_index_type(&arg) + }).filter(|a| a.name.is_some()).collect(); + let output = ret_types.iter().map(|arg| { + get_index_type(&arg) + }).filter(|a| a.name.is_some()).collect::>(); + let output = if output.is_empty() { + None + } else { + Some(output) + }; + + Some(IndexItemFunctionType { inputs, output }) +} + +fn get_index_type(clean_type: &clean::Type) -> Type { + let t = Type { + name: get_index_type_name(clean_type, true).map(|s| s.to_ascii_lowercase()), + generics: get_generics(clean_type), + }; + t +} + +fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option { + match *clean_type { + clean::ResolvedPath { ref path, .. } => { + let segments = &path.segments; + let path_segment = segments.into_iter().last().unwrap_or_else(|| panic!( + "get_index_type_name(clean_type: {:?}, accept_generic: {:?}) had length zero path", + clean_type, accept_generic + )); + Some(path_segment.name.clone()) + } + clean::Generic(ref s) if accept_generic => Some(s.clone()), + clean::Primitive(ref p) => Some(format!("{:?}", p)), + clean::BorrowedRef { ref type_, .. } => get_index_type_name(type_, accept_generic), + // FIXME: add all from clean::Type. + _ => None + } +} + +fn get_generics(clean_type: &clean::Type) -> Option> { + clean_type.generics() + .and_then(|types| { + let r = types.iter() + .filter_map(|t| get_index_type_name(t, false)) + .map(|s| s.to_ascii_lowercase()) + .collect::>(); + if r.is_empty() { + None + } else { + Some(r) + } + }) +} From 6e0b0d4d7094d8d63a3c11325ae8c53c9928aab7 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 13 Sep 2019 11:40:51 -0400 Subject: [PATCH 027/413] Move cache into Context, avoid TLS This doesn't move everything over as cache() is pretty annoying to remove fully, but it gets the ball rolling. --- src/librustdoc/html/render.rs | 55 +++++++++++++++++------------------ 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index ff7134ab7c0d5..dc9e7131c89de 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -167,6 +167,7 @@ struct Context { /// The map used to ensure all generated 'id=' attributes are unique. id_map: Rc>, pub shared: Arc, + pub cache: Arc, } crate struct SharedContext { @@ -477,31 +478,31 @@ pub fn run(mut krate: clean::Crate, let dst = output; scx.ensure_dir(&dst)?; krate = sources::render(&dst, &mut scx, krate)?; + let (new_crate, index, cache) = Cache::from_krate( + renderinfo, + &extern_html_root_urls, + &dst, + krate, + ); + krate = new_crate; + let cache = Arc::new(cache); let mut cx = Context { current: Vec::new(), dst, render_redirect_pages: false, id_map: Rc::new(RefCell::new(id_map)), shared: Arc::new(scx), + cache: cache.clone(), }; - let (new_crate, index, cache) = Cache::from_krate( - renderinfo, - &extern_html_root_urls, - &cx.dst, - krate, - ); - krate = new_crate; - // Freeze the cache now that the index has been built. Put an Arc into TLS // for future parallelization opportunities - let cache = Arc::new(cache); CACHE_KEY.with(|v| *v.borrow_mut() = cache.clone()); CURRENT_DEPTH.with(|s| s.set(0)); // Write shared runs within a flock; disable thread dispatching of IO temporarily. Arc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true); - write_shared(&cx, &krate, &*cache, index, &md_opts, diag)?; + write_shared(&cx, &krate, index, &md_opts, diag)?; Arc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false); // And finally render the whole crate's documentation @@ -519,7 +520,6 @@ pub fn run(mut krate: clean::Crate, fn write_shared( cx: &Context, krate: &clean::Crate, - cache: &Cache, search_index: String, options: &RenderOptions, diag: &errors::Handler, @@ -750,7 +750,7 @@ themePicker.onblur = handleThemeButtonsBlur; { let (mut all_aliases, _, _) = try_err!(collect(&dst, &krate.name, "ALIASES", false), &dst); let mut output = String::with_capacity(100); - for (alias, items) in &cache.aliases { + for (alias, items) in &cx.cache.aliases { if items.is_empty() { continue } @@ -920,7 +920,7 @@ themePicker.onblur = handleThemeButtonsBlur; // Update the list of all implementors for traits let dst = cx.dst.join("implementors"); - for (&did, imps) in &cache.implementors { + for (&did, imps) in &cx.cache.implementors { // Private modules can leak through to this phase of rustdoc, which // could contain implementations for otherwise private types. In some // rare cases we could find an implementation for an item which wasn't @@ -928,9 +928,9 @@ themePicker.onblur = handleThemeButtonsBlur; // // FIXME: this is a vague explanation for why this can't be a `get`, in // theory it should be... - let &(ref remote_path, remote_item_type) = match cache.paths.get(&did) { + let &(ref remote_path, remote_item_type) = match cx.cache.paths.get(&did) { Some(p) => p, - None => match cache.external_paths.get(&did) { + None => match cx.cache.external_paths.get(&did) { Some(p) => p, None => continue, } @@ -958,7 +958,7 @@ themePicker.onblur = handleThemeButtonsBlur; // Only create a js file if we have impls to add to it. If the trait is // documented locally though we always create the file to avoid dead // links. - if !have_impls && !cache.paths.contains_key(&did) { + if !have_impls && !cx.cache.paths.contains_key(&did) { continue; } @@ -1309,7 +1309,7 @@ impl Context { extra_scripts: &[], static_extra_scripts: &[], }; - let sidebar = if let Some(ref version) = cache().crate_version { + let sidebar = if let Some(ref version) = self.cache.crate_version { format!("

    Crate {}

    \
    \

    Version {}

    \ @@ -1399,7 +1399,7 @@ impl Context { &self.shared.themes) } else { let mut url = self.root_path(); - if let Some(&(ref names, ty)) = cache().paths.get(&it.def_id) { + if let Some(&(ref names, ty)) = self.cache.paths.get(&it.def_id) { for name in &names[..names.len() - 1] { url.push_str(name); url.push_str("/"); @@ -1549,7 +1549,6 @@ impl Context { fn src_href(&self, item: &clean::Item) -> Option { let mut root = self.root_path(); - let cache = cache(); let mut path = String::new(); // We can safely ignore macros from other libraries @@ -1565,7 +1564,7 @@ impl Context { return None; } } else { - let (krate, src_root) = match *cache.extern_locations.get(&item.def_id.krate)? { + let (krate, src_root) = match *self.cache.extern_locations.get(&item.def_id.krate)? { (ref name, ref src, Local) => (name, src), (ref name, ref src, Remote(ref s)) => { root = s.to_string(); @@ -2475,11 +2474,9 @@ fn item_trait( // If there are methods directly on this trait object, render them here. render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All); - let cache = cache(); - let mut synthetic_types = Vec::new(); - if let Some(implementors) = cache.implementors.get(&it.def_id) { + if let Some(implementors) = cx.cache.implementors.get(&it.def_id) { // The DefId is for the first Type found with that name. The bool is // if any Types with the same name but different DefId have been found. let mut implementor_dups: FxHashMap<&str, (DefId, bool)> = FxHashMap::default(); @@ -2502,7 +2499,7 @@ fn item_trait( let (local, foreign) = implementors.iter() .partition::, _>(|i| i.inner_impl().for_.def_id() - .map_or(true, |d| cache.paths.contains_key(&d))); + .map_or(true, |d| cx.cache.paths.contains_key(&d))); let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) = local.iter() @@ -2567,7 +2564,7 @@ fn item_trait( path = if it.def_id.is_local() { cx.current.join("/") } else { - let (ref path, _) = cache.external_paths[&it.def_id]; + let (ref path, _) = cx.cache.external_paths[&it.def_id]; path[..path.len() - 1].join("/") }, ty = it.type_(), @@ -3144,7 +3141,7 @@ fn render_assoc_items(w: &mut Buffer, containing_item: &clean::Item, it: DefId, what: AssocItemRender<'_>) { - let c = cache(); + let c = &cx.cache; let v = match c.impls.get(&it) { Some(v) => v, None => return, @@ -3250,7 +3247,7 @@ fn render_deref_methods(w: &mut Buffer, cx: &Context, impl_: &Impl, render_assoc_items(w, cx, container_item, did, what) } else { if let Some(prim) = target.primitive_type() { - if let Some(&did) = cache().primitive_locations.get(&prim) { + if let Some(&did) = cx.cache.primitive_locations.get(&prim) { render_assoc_items(w, cx, container_item, did, what); } } @@ -3500,7 +3497,7 @@ fn render_impl(w: &mut Buffer, cx: &Context, i: &Impl, link: AssocItemLink<'_>, } } - let traits = &cache().traits; + let traits = &cx.cache.traits; let trait_ = i.trait_did().map(|did| &traits[&did]); write!(w, "
    "); @@ -3642,7 +3639,7 @@ fn print_sidebar(cx: &Context, it: &clean::Item, buffer: &mut Buffer) { } if it.is_crate() { - if let Some(ref version) = cache().crate_version { + if let Some(ref version) = cx.cache.crate_version { write!(buffer, "
    \

    Version {}

    \ From 0ad789aa5b0950608b2d71b8388c3d167fcc22b1 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 13 Sep 2019 14:11:10 -0400 Subject: [PATCH 028/413] Stylistic fix -- remove double impl --- src/librustdoc/html/render.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index dc9e7131c89de..2623f8d227e14 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -222,9 +222,7 @@ impl SharedContext { Ok(()) } -} -impl SharedContext { /// Based on whether the `collapse-docs` pass was run, return either the `doc_value` or the /// `collapsed_doc_value` of the given item. pub fn maybe_collapsed_doc_value<'a>(&self, item: &'a clean::Item) -> Option> { From df7789c902eb198a107422dd8e4e4c81ec3cb6ad Mon Sep 17 00:00:00 2001 From: Tomas Tauber <2410580+tomtau@users.noreply.github.com> Date: Sat, 14 Sep 2019 10:06:05 +0800 Subject: [PATCH 029/413] Made a thread local storage panic message more explanatory (TLS is usually understood as Transport Layer Security outside rust-std internals) --- src/libstd/thread/local.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index f85b5d632f16b..a2bbe371de788 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -236,8 +236,8 @@ impl LocalKey { #[stable(feature = "rust1", since = "1.0.0")] pub fn with(&'static self, f: F) -> R where F: FnOnce(&T) -> R { - self.try_with(f).expect("cannot access a TLS value during or \ - after it is destroyed") + self.try_with(f).expect("cannot access a Thread Local Storage value \ + during or after it is destroyed") } /// Acquires a reference to the value in this TLS key. From 146cb8eda667e5d76bebdef3acc61adaeaa025b0 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 7 Sep 2019 15:49:58 +0200 Subject: [PATCH 030/413] or-patterns: remove hack from lowering. --- src/librustc/hir/lowering.rs | 29 ------------------ src/librustc/hir/lowering/expr.rs | 51 ++++++++++++------------------- src/libsyntax/visit.rs | 2 -- 3 files changed, 19 insertions(+), 63 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 58789a10609b7..a5f08cd96061f 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -434,35 +434,6 @@ impl<'a> LoweringContext<'a> { visit::walk_pat(self, p) } - // HACK(or_patterns; Centril | dlrobertson): Avoid creating - // HIR nodes for `PatKind::Or` for the top level of a `ast::Arm`. - // This is a temporary hack that should go away once we push down - // `arm.pats: HirVec>` -> `arm.pat: P` to HIR. // Centril - fn visit_arm(&mut self, arm: &'tcx Arm) { - match &arm.pat.node { - PatKind::Or(pats) => pats.iter().for_each(|p| self.visit_pat(p)), - _ => self.visit_pat(&arm.pat), - } - walk_list!(self, visit_expr, &arm.guard); - self.visit_expr(&arm.body); - walk_list!(self, visit_attribute, &arm.attrs); - } - - // HACK(or_patterns; Centril | dlrobertson): Same as above. // Centril - fn visit_expr(&mut self, e: &'tcx Expr) { - if let ExprKind::Let(pat, scrutinee) = &e.node { - walk_list!(self, visit_attribute, e.attrs.iter()); - match &pat.node { - PatKind::Or(pats) => pats.iter().for_each(|p| self.visit_pat(p)), - _ => self.visit_pat(&pat), - } - self.visit_expr(scrutinee); - self.visit_expr_post(e); - return; - } - visit::walk_expr(self, e) - } - fn visit_item(&mut self, item: &'tcx Item) { let hir_id = self.lctx.allocate_hir_id_counter(item.id); diff --git a/src/librustc/hir/lowering/expr.rs b/src/librustc/hir/lowering/expr.rs index a46cdabbb518f..d71dc53d104af 100644 --- a/src/librustc/hir/lowering/expr.rs +++ b/src/librustc/hir/lowering/expr.rs @@ -250,14 +250,14 @@ impl LoweringContext<'_> { // 4. The return type of the block is `bool` which seems like what the user wanted. let scrutinee = self.lower_expr(scrutinee); let then_arm = { - let pat = self.lower_pat_top_hack(pat); + let pat = self.lower_pat(pat); let expr = self.expr_bool(span, true); self.arm(pat, P(expr)) }; let else_arm = { let pat = self.pat_wild(span); let expr = self.expr_bool(span, false); - self.arm(hir_vec![pat], P(expr)) + self.arm(pat, P(expr)) }; hir::ExprKind::Match( P(scrutinee), @@ -281,7 +281,7 @@ impl LoweringContext<'_> { None => (self.expr_block_empty(span), false), Some(els) => (self.lower_expr(els), true), }; - let else_arm = self.arm(hir_vec![else_pat], P(else_expr)); + let else_arm = self.arm(else_pat, P(else_expr)); // Handle then + scrutinee: let then_blk = self.lower_block(then, false); @@ -290,7 +290,7 @@ impl LoweringContext<'_> { // ` => `: ExprKind::Let(ref pat, ref scrutinee) => { let scrutinee = self.lower_expr(scrutinee); - let pat = self.lower_pat_top_hack(pat); + let pat = self.lower_pat(pat); (pat, scrutinee, hir::MatchSource::IfLetDesugar { contains_else_clause }) } // `true => `: @@ -307,7 +307,7 @@ impl LoweringContext<'_> { // let temporaries live outside of `cond`. let cond = self.expr_drop_temps(span_block, P(cond), ThinVec::new()); let pat = self.pat_bool(span, true); - (hir_vec![pat], cond, hir::MatchSource::IfDesugar { contains_else_clause }) + (pat, cond, hir::MatchSource::IfDesugar { contains_else_clause }) } }; let then_arm = self.arm(then_pat, P(then_expr)); @@ -331,7 +331,7 @@ impl LoweringContext<'_> { let else_arm = { let else_pat = self.pat_wild(span); let else_expr = self.expr_break(span, ThinVec::new()); - self.arm(hir_vec![else_pat], else_expr) + self.arm(else_pat, else_expr) }; // Handle then + scrutinee: @@ -348,7 +348,7 @@ impl LoweringContext<'_> { // } // } let scrutinee = self.with_loop_condition_scope(|t| t.lower_expr(scrutinee)); - let pat = self.lower_pat_top_hack(pat); + let pat = self.lower_pat(pat); (pat, scrutinee, hir::MatchSource::WhileLetDesugar, hir::LoopSource::WhileLet) } _ => { @@ -376,7 +376,7 @@ impl LoweringContext<'_> { let cond = self.expr_drop_temps(span_block, P(cond), ThinVec::new()); // `true => `: let pat = self.pat_bool(span, true); - (hir_vec![pat], cond, hir::MatchSource::WhileDesugar, hir::LoopSource::While) + (pat, cond, hir::MatchSource::WhileDesugar, hir::LoopSource::While) } }; let then_arm = self.arm(then_pat, P(then_expr)); @@ -429,7 +429,7 @@ impl LoweringContext<'_> { hir::Arm { hir_id: self.next_id(), attrs: self.lower_attrs(&arm.attrs), - pats: self.lower_pat_top_hack(&arm.pat), + pat: self.lower_pat(&arm.pat), guard: match arm.guard { Some(ref x) => Some(hir::Guard::If(P(self.lower_expr(x)))), _ => None, @@ -439,16 +439,6 @@ impl LoweringContext<'_> { } } - /// HACK(or_patterns; Centril | dlrobertson): For now we don't push down top level or-patterns - /// `p | q` into `hir::PatKind::Or(...)` as post-lowering bits of the compiler are not ready - /// to deal with it. This should by fixed by pushing it down to HIR and then HAIR. - fn lower_pat_top_hack(&mut self, pat: &Pat) -> HirVec> { - match pat.node { - PatKind::Or(ref ps) => ps.iter().map(|x| self.lower_pat(x)).collect(), - _ => hir_vec![self.lower_pat(pat)], - } - } - pub(super) fn make_async_expr( &mut self, capture_clause: CaptureBy, @@ -597,7 +587,7 @@ impl LoweringContext<'_> { ); P(this.expr(await_span, expr_break, ThinVec::new())) }); - self.arm(hir_vec![ready_pat], break_x) + self.arm(ready_pat, break_x) }; // `::std::task::Poll::Pending => {}` @@ -608,7 +598,7 @@ impl LoweringContext<'_> { hir_vec![], ); let empty_block = P(self.expr_block_empty(span)); - self.arm(hir_vec![pending_pat], empty_block) + self.arm(pending_pat, empty_block) }; let inner_match_stmt = { @@ -650,7 +640,7 @@ impl LoweringContext<'_> { }); // mut pinned => loop { ... } - let pinned_arm = self.arm(hir_vec![pinned_pat], loop_expr); + let pinned_arm = self.arm(pinned_pat, loop_expr); // match { // mut pinned => loop { .. } @@ -1084,7 +1074,7 @@ impl LoweringContext<'_> { ThinVec::new(), )); let some_pat = self.pat_some(pat.span, val_pat); - self.arm(hir_vec![some_pat], assign) + self.arm(some_pat, assign) }; // `::std::option::Option::None => break` @@ -1092,7 +1082,7 @@ impl LoweringContext<'_> { let break_expr = self.with_loop_scope(e.id, |this| this.expr_break(e.span, ThinVec::new())); let pat = self.pat_none(e.span); - self.arm(hir_vec![pat], break_expr) + self.arm(pat, break_expr) }; // `mut iter` @@ -1163,7 +1153,7 @@ impl LoweringContext<'_> { }); // `mut iter => { ... }` - let iter_arm = self.arm(hir_vec![iter_pat], loop_expr); + let iter_arm = self.arm(iter_pat, loop_expr); // `match ::std::iter::IntoIterator::into_iter() { ... }` let into_iter_expr = { @@ -1249,7 +1239,7 @@ impl LoweringContext<'_> { ThinVec::from(attrs.clone()), )); let ok_pat = self.pat_ok(span, val_pat); - self.arm(hir_vec![ok_pat], val_expr) + self.arm(ok_pat, val_expr) }; // `Err(err) => #[allow(unreachable_code)] @@ -1284,7 +1274,7 @@ impl LoweringContext<'_> { }; let err_pat = self.pat_err(try_span, err_local); - self.arm(hir_vec![err_pat], ret_expr) + self.arm(err_pat, ret_expr) }; hir::ExprKind::Match( @@ -1479,14 +1469,11 @@ impl LoweringContext<'_> { } } - /// HACK(or_patterns; Centril | dlrobertson): For now we don't push down top level or-patterns - /// `p | q` into `hir::PatKind::Or(...)` as post-lowering bits of the compiler are not ready - /// to deal with it. This should by fixed by pushing it down to HIR and then HAIR. - fn arm(&mut self, pats: HirVec>, expr: P) -> hir::Arm { + fn arm(&mut self, pat: P, expr: P) -> hir::Arm { hir::Arm { hir_id: self.next_id(), attrs: hir_vec![], - pats, + pat, guard: None, span: expr.span, body: expr, diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index d7c537be89668..4fc29d70540fd 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -834,8 +834,6 @@ pub fn walk_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Param) { pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) { visitor.visit_pat(&arm.pat); - // NOTE(or_patterns; Centril | dlrobertson): - // If you change this, also change the hack in `lowering.rs`. walk_list!(visitor, visit_expr, &arm.guard); visitor.visit_expr(&arm.body); walk_list!(visitor, visit_attribute, &arm.attrs); From b2f903c066185d32bdfc02ff6a35f4e50c54728d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 7 Sep 2019 16:00:09 +0200 Subject: [PATCH 031/413] or-patterns: `hir::Arm::pats` -> `::pat` + `Arm::top_pats_hack`. --- src/librustc/hir/mod.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 2c8590aa4e3fa..1b32979eda5f4 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1259,21 +1259,32 @@ pub struct Local { } /// Represents a single arm of a `match` expression, e.g. -/// ` (if ) => `. +/// ` (if ) => `. #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub struct Arm { #[stable_hasher(ignore)] pub hir_id: HirId, pub span: Span, pub attrs: HirVec, - /// Multiple patterns can be combined with `|` - pub pats: HirVec>, + /// If this pattern and the optional guard matches, then `body` is evaluated. + pub pat: P, /// Optional guard clause. pub guard: Option, /// The expression the arm evaluates to if this arm matches. pub body: P, } +impl Arm { + // HACK(or_patterns; Centril | dlrobertson): Remove this and + // correctly handle each case in which this method is used. + pub fn top_pats_hack(&self) -> &[P] { + match &self.pat.node { + PatKind::Or(pats) => pats, + _ => std::slice::from_ref(&self.pat), + } + } +} + #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum Guard { If(P), From 6579d136b13d6b8a3ad14afe688a8c368a538b57 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 7 Sep 2019 16:00:39 +0200 Subject: [PATCH 032/413] or-patterns: normalize HIR pretty priting. --- src/librustc/hir/print.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index cfbfb5eceb550..3cbc9ebec0ad8 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1790,16 +1790,7 @@ impl<'a> State<'a> { self.ann.pre(self, AnnNode::Arm(arm)); self.ibox(0); self.print_outer_attributes(&arm.attrs); - let mut first = true; - for p in &arm.pats { - if first { - first = false; - } else { - self.s.space(); - self.word_space("|"); - } - self.print_pat(&p); - } + self.print_pat(&arm.pat); self.s.space(); if let Some(ref g) = arm.guard { match g { From 75fb42a11fa91a323e2109a0d42230d96c73e3bb Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 7 Sep 2019 16:01:12 +0200 Subject: [PATCH 033/413] or-patterns: use `top_pats_hack` to make things compile. --- src/librustc/hir/intravisit.rs | 2 +- src/librustc/hir/pat_util.rs | 2 +- src/librustc/middle/dead.rs | 5 +++-- src/librustc/middle/expr_use_visitor.rs | 4 ++-- src/librustc/middle/liveness.rs | 6 +++--- src/librustc_ast_borrowck/cfg/construct.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 2 +- src/librustc_mir/hair/pattern/check_match.rs | 6 +++--- src/librustc_passes/rvalue_promotion.rs | 2 +- src/librustc_typeck/check/_match.rs | 8 +++----- src/librustc_typeck/check/regionck.rs | 4 ++-- 11 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 1f125de967216..91fc004b893ba 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -1103,7 +1103,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) { visitor.visit_id(arm.hir_id); - walk_list!(visitor, visit_pat, &arm.pats); + visitor.visit_pat(&arm.pat); if let Some(ref g) = arm.guard { match g { Guard::If(ref e) => visitor.visit_expr(e), diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index 0d2c7d393bb89..3d82f37e1a9c3 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -170,7 +170,7 @@ impl hir::Arm { // for #42640 (default match binding modes). // // See #44848. - self.pats.iter() + self.top_pats_hack().iter() .filter_map(|pat| pat.contains_explicit_ref_binding()) .max_by_key(|m| match *m { hir::MutMutable => 1, diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index d4805a7c78322..666c1cc96f2f7 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -259,8 +259,9 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { } fn visit_arm(&mut self, arm: &'tcx hir::Arm) { - if arm.pats.len() == 1 { - let variants = arm.pats[0].necessary_variants(); + let pats = arm.top_pats_hack(); + if pats.len() == 1 { + let variants = pats[0].necessary_variants(); // Inside the body, ignore constructions of variants // necessary for the pattern to match. Those construction sites diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index de6dadabcbf56..ef84c9bbad60d 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -779,14 +779,14 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { fn arm_move_mode(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &hir::Arm) -> TrackMatchMode { let mut mode = Unknown; - for pat in &arm.pats { + for pat in arm.top_pats_hack() { self.determine_pat_move_mode(discr_cmt.clone(), &pat, &mut mode); } mode } fn walk_arm(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &hir::Arm, mode: MatchMode) { - for pat in &arm.pats { + for pat in arm.top_pats_hack() { self.walk_pat(discr_cmt.clone(), &pat, mode); } diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 00013bfc574f4..5e91c81dd4ded 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -456,7 +456,7 @@ fn visit_local<'tcx>(ir: &mut IrMaps<'tcx>, local: &'tcx hir::Local) { } fn visit_arm<'tcx>(ir: &mut IrMaps<'tcx>, arm: &'tcx hir::Arm) { - for pat in &arm.pats { + for pat in arm.top_pats_hack() { add_from_pat(ir, pat); } intravisit::walk_arm(ir, arm); @@ -1080,7 +1080,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // the same bindings, and we also consider the first pattern to be // the "authoritative" set of ids let arm_succ = - self.define_bindings_in_arm_pats(arm.pats.first().map(|p| &**p), + self.define_bindings_in_arm_pats(arm.top_pats_hack().first().map(|p| &**p), guard_succ); self.merge_from_succ(ln, arm_succ, first_merge); first_merge = false; @@ -1422,7 +1422,7 @@ fn check_arm<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, arm: &'tcx hir::Arm) { // patterns so the suggestions to prefix with underscores will apply to those too. let mut vars: BTreeMap)> = Default::default(); - for pat in &arm.pats { + for pat in arm.top_pats_hack() { this.arm_pats_bindings(Some(&*pat), |this, ln, var, sp, id| { let name = this.ir.variable_name(var); vars.entry(name) diff --git a/src/librustc_ast_borrowck/cfg/construct.rs b/src/librustc_ast_borrowck/cfg/construct.rs index 0dc999083a91a..e2c5de648a276 100644 --- a/src/librustc_ast_borrowck/cfg/construct.rs +++ b/src/librustc_ast_borrowck/cfg/construct.rs @@ -390,7 +390,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // patterns and the guard (if there is one) in the arm. let bindings_exit = self.add_dummy_node(&[]); - for pat in &arm.pats { + for pat in arm.top_pats_hack() { // Visit the pattern, coming from the discriminant exit let mut pat_exit = self.pat(&pat, discr_exit); diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index a33d7207ed4e1..f3d699fa4f008 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -862,7 +862,7 @@ impl ToBorrowKind for hir::Mutability { fn convert_arm<'a, 'tcx>(cx: &mut Cx<'a, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> { Arm { - patterns: arm.pats.iter().map(|p| cx.pattern_from_hir(p)).collect(), + patterns: arm.top_pats_hack().iter().map(|p| cx.pattern_from_hir(p)).collect(), guard: match arm.guard { Some(hir::Guard::If(ref e)) => Some(Guard::If(e.to_ref())), _ => None, diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 161c58a175579..c3542d4ab6c5f 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -137,7 +137,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { ) { for arm in arms { // First, check legality of move bindings. - self.check_patterns(arm.guard.is_some(), &arm.pats); + self.check_patterns(arm.guard.is_some(), &arm.top_pats_hack()); // Second, if there is a guard on each arm, make sure it isn't // assigning or borrowing anything mutably. @@ -146,7 +146,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { } // Third, perform some lints. - for pat in &arm.pats { + for pat in arm.top_pats_hack() { check_for_bindings_named_same_as_variants(self, pat); } } @@ -156,7 +156,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { let mut have_errors = false; let inlined_arms : Vec<(Vec<_>, _)> = arms.iter().map(|arm| ( - arm.pats.iter().map(|pat| { + arm.top_pats_hack().iter().map(|pat| { let mut patcx = PatternContext::new(self.tcx, self.param_env.and(self.identity_substs), self.tables); diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index f2461f7016131..7470f5b7a5f0f 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -503,7 +503,7 @@ fn check_expr_kind<'a, 'tcx>( // Compute the most demanding borrow from all the arms' // patterns and set that on the discriminator. let mut mut_borrow = false; - for pat in hirvec_arm.iter().flat_map(|arm| &arm.pats) { + for pat in hirvec_arm.iter().flat_map(|arm| arm.top_pats_hack()) { mut_borrow = v.remove_mut_rvalue_borrow(pat); } if mut_borrow { diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 308a3d8ebc2cf..7b971803db599 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -58,11 +58,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // collection into `Vec`), so we get types for all bindings. let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| { let mut all_pats_diverge = Diverges::WarnedAlways; - for p in &arm.pats { - self.diverges.set(Diverges::Maybe); - self.check_pat_top(&p, discrim_ty, Some(discrim.span)); - all_pats_diverge &= self.diverges.get(); - } + self.diverges.set(Diverges::Maybe); + self.check_pat_top(&arm.pat, discrim_ty, Some(discrim.span)); + all_pats_diverge &= self.diverges.get(); // As discussed with @eddyb, this is for disabling unreachable_code // warnings on patterns (they're now subsumed by unreachable_patterns diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index fc01a820e2359..86ec477a6aae8 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -488,7 +488,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> { fn visit_arm(&mut self, arm: &'tcx hir::Arm) { // see above - for p in &arm.pats { + for p in arm.top_pats_hack() { self.constrain_bindings_in_pat(p); } intravisit::walk_arm(self, arm); @@ -1069,7 +1069,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { let discr_cmt = Rc::new(ignore_err!(self.with_mc(|mc| mc.cat_expr(discr)))); debug!("discr_cmt={:?}", discr_cmt); for arm in arms { - for root_pat in &arm.pats { + for root_pat in arm.top_pats_hack() { self.link_pattern(discr_cmt.clone(), &root_pat); } } From 89bbef302646c4b33148e2a34b69de7643a55ffa Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 15 Sep 2019 02:48:53 +0200 Subject: [PATCH 034/413] check_match: misc cleanup. --- src/librustc_mir/hair/pattern/check_match.rs | 43 ++++++++------------ src/librustc_mir/lib.rs | 1 + 2 files changed, 17 insertions(+), 27 deletions(-) diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index c3542d4ab6c5f..dc884d40ac157 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -563,40 +563,30 @@ fn check_legality_of_move_bindings( } }) } + let span_vec = &mut Vec::new(); - let check_move = | - cx: &mut MatchVisitor<'_, '_>, - p: &Pat, - sub: Option<&Pat>, - span_vec: &mut Vec, - | { - // check legality of moving out of the enum - - // x @ Foo(..) is legal, but x @ Foo(y) isn't. + let mut check_move = |p: &Pat, sub: Option<&Pat>| { + // Check legality of moving out of the enum. + // + // `x @ Foo(..)` is legal, but `x @ Foo(y)` isn't. if sub.map_or(false, |p| p.contains_bindings()) { - struct_span_err!(cx.tcx.sess, p.span, E0007, - "cannot bind by-move with sub-bindings") + struct_span_err!(cx.tcx.sess, p.span, E0007, "cannot bind by-move with sub-bindings") .span_label(p.span, "binds an already bound by-move value by moving it") .emit(); - } else if !has_guard { - if let Some(_by_ref_span) = by_ref_span { - span_vec.push(p.span); - } + } else if !has_guard && by_ref_span.is_some() { + span_vec.push(p.span); } }; for pat in pats { pat.walk(|p| { - if let PatKind::Binding(_, _, _, ref sub) = p.node { + if let PatKind::Binding(.., sub) = &p.node { if let Some(&bm) = cx.tables.pat_binding_modes().get(p.hir_id) { - match bm { - ty::BindByValue(..) => { - let pat_ty = cx.tables.node_type(p.hir_id); - if !pat_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, pat.span) { - check_move(cx, p, sub.as_ref().map(|p| &**p), span_vec); - } + if let ty::BindByValue(..) = bm { + let pat_ty = cx.tables.node_type(p.hir_id); + if !pat_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, pat.span) { + check_move(p, sub.as_deref()); } - _ => {} } } else { cx.tcx.sess.delay_span_bug(pat.span, "missing binding mode"); @@ -605,11 +595,10 @@ fn check_legality_of_move_bindings( true }); } - if !span_vec.is_empty(){ - let span = MultiSpan::from_spans(span_vec.clone()); + if !span_vec.is_empty() { let mut err = struct_span_err!( cx.tcx.sess, - span, + MultiSpan::from_spans(span_vec.clone()), E0009, "cannot bind by-move and by-ref in the same pattern", ); @@ -627,7 +616,7 @@ fn check_legality_of_move_bindings( /// because of the way rvalues are handled in the borrow check. (See issue /// #14587.) fn check_legality_of_bindings_in_at_patterns(cx: &MatchVisitor<'_, '_>, pat: &Pat) { - AtBindingPatternVisitor { cx: cx, bindings_allowed: true }.visit_pat(pat); + AtBindingPatternVisitor { cx, bindings_allowed: true }.visit_pat(pat); } struct AtBindingPatternVisitor<'a, 'b, 'tcx> { diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index f27db351b74db..ac756747aa326 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -6,6 +6,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(nll)] #![feature(in_band_lifetimes)] +#![feature(inner_deref)] #![feature(slice_patterns)] #![feature(box_patterns)] #![feature(box_syntax)] From 4c346939b088cf07ece818b7dc093f993eae2578 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 15 Sep 2019 02:49:37 +0200 Subject: [PATCH 035/413] or-patterns: fix problems in typeck. --- src/librustc_typeck/check/pat.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 8502b89de1469..c8869132fb654 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -97,11 +97,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_pat_struct(pat, qpath, fields, *etc, expected, def_bm, discrim_span) } PatKind::Or(pats) => { - let expected_ty = self.structurally_resolved_type(pat.span, expected); for pat in pats { self.check_pat(pat, expected, def_bm, discrim_span); } - expected_ty + expected } PatKind::Tuple(elements, ddpos) => { self.check_pat_tuple(pat.span, elements, *ddpos, expected, def_bm, discrim_span) @@ -208,7 +207,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match pat.node { PatKind::Struct(..) | PatKind::TupleStruct(..) | - PatKind::Or(_) | PatKind::Tuple(..) | PatKind::Box(_) | PatKind::Range(..) | @@ -226,6 +224,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => true, } } + // FIXME(or_patterns; Centril | dlrobertson): To keep things compiling + // for or-patterns at the top level, we need to make `p_0 | ... | p_n` + // a "non reference pattern". For example the following currently compiles: + // ``` + // match &1 { + // e @ &(1...2) | e @ &(3...4) => {} + // _ => {} + // } + // ``` + // + // We should consider whether we should do something special in nested or-patterns. + PatKind::Or(_) | PatKind::Wild | PatKind::Binding(..) | PatKind::Ref(..) => false, @@ -426,12 +436,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the binding is like `ref x | ref const x | ref mut x` // then `x` is assigned a value of type `&M T` where M is the // mutability and T is the expected type. - let region_ty = self.new_ref_ty(pat.span, mutbl, expected); - + // // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` // is required. However, we use equality, which is stronger. // See (note_1) for an explanation. - region_ty + self.new_ref_ty(pat.span, mutbl, expected) } // Otherwise, the type of x is the expected type `T`. ty::BindByValue(_) => { From 9d1c3c96e7866d6f82b92fffa00fac59f418b601 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 15 Sep 2019 03:26:51 +0200 Subject: [PATCH 036/413] simplify `hir::Pat::walk_`. --- src/librustc/hir/mod.rs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 1b32979eda5f4..edb55ab3caaf4 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -889,19 +889,14 @@ impl Pat { return false; } - match self.node { - PatKind::Binding(.., Some(ref p)) => p.walk_(it), - PatKind::Struct(_, ref fields, _) => { - fields.iter().all(|field| field.pat.walk_(it)) - } - PatKind::TupleStruct(_, ref s, _) | PatKind::Tuple(ref s, _) => { + match &self.node { + PatKind::Binding(.., Some(p)) => p.walk_(it), + PatKind::Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_(it)), + PatKind::TupleStruct(_, s, _) | PatKind::Tuple(s, _) | PatKind::Or(s) => { s.iter().all(|p| p.walk_(it)) } - PatKind::Or(ref pats) => pats.iter().all(|p| p.walk_(it)), - PatKind::Box(ref s) | PatKind::Ref(ref s, _) => { - s.walk_(it) - } - PatKind::Slice(ref before, ref slice, ref after) => { + PatKind::Box(s) | PatKind::Ref(s, _) => s.walk_(it), + PatKind::Slice(before, slice, after) => { before.iter() .chain(slice.iter()) .chain(after.iter()) From cc5fe6d520683e847d1d5fd2a4544e2a5dba9ab4 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 15 Sep 2019 03:55:34 +0200 Subject: [PATCH 037/413] or-patterns: liveness/`visit_arm`: remove `top_pats_hack`. --- src/librustc/middle/liveness.rs | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 5e91c81dd4ded..3c264f9ac6e6c 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -404,7 +404,7 @@ fn visit_fn<'tcx>( lsets.warn_about_unused_args(body, entry_ln); } -fn add_from_pat<'tcx>(ir: &mut IrMaps<'tcx>, pat: &P) { +fn add_from_pat(ir: &mut IrMaps<'_>, pat: &P) { // For struct patterns, take note of which fields used shorthand // (`x` rather than `x: x`). let mut shorthand_field_ids = HirIdSet::default(); @@ -412,26 +412,21 @@ fn add_from_pat<'tcx>(ir: &mut IrMaps<'tcx>, pat: &P) { pats.push_back(pat); while let Some(pat) = pats.pop_front() { use crate::hir::PatKind::*; - match pat.node { - Binding(_, _, _, ref inner_pat) => { + match &pat.node { + Binding(.., inner_pat) => { pats.extend(inner_pat.iter()); } - Struct(_, ref fields, _) => { - for field in fields { - if field.is_shorthand { - shorthand_field_ids.insert(field.pat.hir_id); - } - } + Struct(_, fields, _) => { + let ids = fields.iter().filter(|f| f.is_shorthand).map(|f| f.pat.hir_id); + shorthand_field_ids.extend(ids); } - Ref(ref inner_pat, _) | - Box(ref inner_pat) => { + Ref(inner_pat, _) | Box(inner_pat) => { pats.push_back(inner_pat); } - TupleStruct(_, ref inner_pats, _) | - Tuple(ref inner_pats, _) => { + TupleStruct(_, inner_pats, _) | Tuple(inner_pats, _) | Or(inner_pats) => { pats.extend(inner_pats.iter()); } - Slice(ref pre_pats, ref inner_pat, ref post_pats) => { + Slice(pre_pats, inner_pat, post_pats) => { pats.extend(pre_pats.iter()); pats.extend(inner_pat.iter()); pats.extend(post_pats.iter()); @@ -440,7 +435,7 @@ fn add_from_pat<'tcx>(ir: &mut IrMaps<'tcx>, pat: &P) { } } - pat.each_binding(|_bm, hir_id, _sp, ident| { + pat.each_binding(|_, hir_id, _, ident| { ir.add_live_node_for_node(hir_id, VarDefNode(ident.span)); ir.add_variable(Local(LocalInfo { id: hir_id, @@ -456,9 +451,7 @@ fn visit_local<'tcx>(ir: &mut IrMaps<'tcx>, local: &'tcx hir::Local) { } fn visit_arm<'tcx>(ir: &mut IrMaps<'tcx>, arm: &'tcx hir::Arm) { - for pat in arm.top_pats_hack() { - add_from_pat(ir, pat); - } + add_from_pat(ir, &arm.pat); intravisit::walk_arm(ir, arm); } From 9ca42a56000d261be74db41339beff06bc6088c9 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 15 Sep 2019 03:41:21 +0200 Subject: [PATCH 038/413] or-patterns: liveness: generalize + remove `top_pats_hack`. --- src/librustc/hir/pat_util.rs | 28 ++++ src/librustc/middle/liveness.rs | 288 +++++++++++++------------------- 2 files changed, 141 insertions(+), 175 deletions(-) diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index 3d82f37e1a9c3..b68886ba62c2d 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -77,6 +77,34 @@ impl hir::Pat { }); } + /// Call `f` on every "binding" in a pattern, e.g., on `a` in + /// `match foo() { Some(a) => (), None => () }`. + /// + /// When encountering an or-pattern `p_0 | ... | p_n` only `p_0` will be visited. + pub fn each_binding_or_first(&self, c: &mut F) + where F: FnMut(hir::BindingAnnotation, HirId, Span, ast::Ident), + { + match &self.node { + PatKind::Binding(bm, _, ident, sub) => { + c(*bm, self.hir_id, self.span, *ident); + sub.iter().for_each(|p| p.each_binding_or_first(c)); + } + PatKind::Or(ps) => ps[0].each_binding_or_first(c), + PatKind::Struct(_, fs, _) => fs.iter().for_each(|f| f.pat.each_binding_or_first(c)), + PatKind::TupleStruct(_, ps, _) | PatKind::Tuple(ps, _) => { + ps.iter().for_each(|p| p.each_binding_or_first(c)); + } + PatKind::Box(p) | PatKind::Ref(p, _) => p.each_binding_or_first(c), + PatKind::Slice(before, slice, after) => { + before.iter() + .chain(slice.iter()) + .chain(after.iter()) + .for_each(|p| p.each_binding_or_first(c)); + } + PatKind::Wild | PatKind::Lit(_) | PatKind::Range(..) | PatKind::Path(_) => {} + } + } + /// Checks if the pattern contains any patterns that bind something to /// an ident, e.g., `foo`, or `Foo(foo)` or `foo @ Bar(..)`. pub fn contains_bindings(&self) -> bool { diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 3c264f9ac6e6c..9afd147ae34e2 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -96,7 +96,11 @@ use self::LiveNodeKind::*; use self::VarKind::*; +use crate::hir; +use crate::hir::{Expr, HirId}; use crate::hir::def::*; +use crate::hir::def_id::DefId; +use crate::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; use crate::hir::Node; use crate::hir::ptr::P; use crate::ty::{self, TyCtxt}; @@ -105,20 +109,16 @@ use crate::lint; use crate::util::nodemap::{HirIdMap, HirIdSet}; use errors::Applicability; -use std::collections::{BTreeMap, VecDeque}; +use rustc_data_structures::fx::FxIndexMap; +use std::collections::VecDeque; use std::{fmt, u32}; use std::io::prelude::*; use std::io; use std::rc::Rc; use syntax::ast; -use syntax::symbol::{kw, sym}; +use syntax::symbol::sym; use syntax_pos::Span; -use crate::hir; -use crate::hir::{Expr, HirId}; -use crate::hir::def_id::DefId; -use crate::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; - #[derive(Copy, Clone, PartialEq)] struct Variable(u32); @@ -727,35 +727,15 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.ir.variable(hir_id, span) } - fn pat_bindings(&mut self, pat: &hir::Pat, mut f: F) where - F: FnMut(&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, HirId), - { - pat.each_binding(|_bm, hir_id, sp, n| { - let ln = self.live_node(hir_id, sp); - let var = self.variable(hir_id, n.span); - f(self, ln, var, n.span, hir_id); - }) - } - - fn arm_pats_bindings(&mut self, pat: Option<&hir::Pat>, f: F) where - F: FnMut(&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, HirId), - { - if let Some(pat) = pat { - self.pat_bindings(pat, f); - } - } - - fn define_bindings_in_pat(&mut self, pat: &hir::Pat, succ: LiveNode) - -> LiveNode { - self.define_bindings_in_arm_pats(Some(pat), succ) - } - - fn define_bindings_in_arm_pats(&mut self, pat: Option<&hir::Pat>, succ: LiveNode) - -> LiveNode { - let mut succ = succ; - self.arm_pats_bindings(pat, |this, ln, var, _sp, _id| { - this.init_from_succ(ln, succ); - this.define(ln, var); + fn define_bindings_in_pat(&mut self, pat: &hir::Pat, mut succ: LiveNode) -> LiveNode { + // In an or-pattern, only consider the first pattern; any later patterns + // must have the same bindings, and we also consider the first pattern + // to be the "authoritative" set of ids. + pat.each_binding_or_first(&mut |_, hir_id, pat_sp, ident| { + let ln = self.live_node(hir_id, pat_sp); + let var = self.variable(hir_id, ident.span); + self.init_from_succ(ln, succ); + self.define(ln, var); succ = ln; }); succ @@ -1069,12 +1049,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { arm.guard.as_ref().map(|hir::Guard::If(e)| &**e), body_succ ); - // only consider the first pattern; any later patterns must have - // the same bindings, and we also consider the first pattern to be - // the "authoritative" set of ids - let arm_succ = - self.define_bindings_in_arm_pats(arm.top_pats_hack().first().map(|p| &**p), - guard_succ); + let arm_succ = self.define_bindings_in_pat(&arm.pat, guard_succ); self.merge_from_succ(ln, arm_succ, first_merge); first_merge = false; }; @@ -1381,74 +1356,36 @@ impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> { NestedVisitorMap::None } - fn visit_local(&mut self, l: &'tcx hir::Local) { - check_local(self, l); - } - fn visit_expr(&mut self, ex: &'tcx Expr) { - check_expr(self, ex); - } - fn visit_arm(&mut self, a: &'tcx hir::Arm) { - check_arm(self, a); - } -} + fn visit_local(&mut self, local: &'tcx hir::Local) { + self.check_unused_vars_in_pat(&local.pat, None, |spans, hir_id, ln, var| { + if local.init.is_some() { + self.warn_about_dead_assign(spans, hir_id, ln, var); + } + }); -fn check_local<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, local: &'tcx hir::Local) { - match local.init { - Some(_) => { - this.warn_about_unused_or_dead_vars_in_pat(&local.pat); - }, - None => { - this.pat_bindings(&local.pat, |this, ln, var, sp, id| { - let span = local.pat.simple_ident().map_or(sp, |ident| ident.span); - this.warn_about_unused(vec![span], id, ln, var); - }) - } + intravisit::walk_local(self, local); } - intravisit::walk_local(this, local); -} - -fn check_arm<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, arm: &'tcx hir::Arm) { - // Only consider the variable from the first pattern; any later patterns must have - // the same bindings, and we also consider the first pattern to be the "authoritative" set of - // ids. However, we should take the spans of variables with the same name from the later - // patterns so the suggestions to prefix with underscores will apply to those too. - let mut vars: BTreeMap)> = Default::default(); - - for pat in arm.top_pats_hack() { - this.arm_pats_bindings(Some(&*pat), |this, ln, var, sp, id| { - let name = this.ir.variable_name(var); - vars.entry(name) - .and_modify(|(.., spans)| { - spans.push(sp); - }) - .or_insert_with(|| { - (ln, var, id, vec![sp]) - }); - }); + fn visit_expr(&mut self, ex: &'tcx Expr) { + check_expr(self, ex); } - for (_, (ln, var, id, spans)) in vars { - this.warn_about_unused(spans, id, ln, var); + fn visit_arm(&mut self, arm: &'tcx hir::Arm) { + self.check_unused_vars_in_pat(&arm.pat, None, |_, _, _, _| {}); + intravisit::walk_arm(self, arm); } - - intravisit::walk_arm(this, arm); } -fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { +fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr) { match expr.node { hir::ExprKind::Assign(ref l, _) => { this.check_place(&l); - - intravisit::walk_expr(this, expr); } hir::ExprKind::AssignOp(_, ref l, _) => { if !this.tables.is_method_call(expr) { this.check_place(&l); } - - intravisit::walk_expr(this, expr); } hir::ExprKind::InlineAsm(ref ia, ref outputs, ref inputs) => { @@ -1463,8 +1400,6 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { } this.visit_expr(output); } - - intravisit::walk_expr(this, expr); } // no correctness conditions related to liveness @@ -1477,13 +1412,13 @@ fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { hir::ExprKind::Lit(_) | hir::ExprKind::Block(..) | hir::ExprKind::AddrOf(..) | hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) | hir::ExprKind::Closure(..) | hir::ExprKind::Path(_) | hir::ExprKind::Yield(..) | - hir::ExprKind::Box(..) | hir::ExprKind::Type(..) | hir::ExprKind::Err => { - intravisit::walk_expr(this, expr); - } + hir::ExprKind::Box(..) | hir::ExprKind::Type(..) | hir::ExprKind::Err => {} } + + intravisit::walk_expr(this, expr); } -impl<'a, 'tcx> Liveness<'a, 'tcx> { +impl<'tcx> Liveness<'_, 'tcx> { fn check_place(&mut self, expr: &'tcx Expr) { match expr.node { hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => { @@ -1496,7 +1431,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // as being used. let ln = self.live_node(expr.hir_id, expr.span); let var = self.variable(var_hid, expr.span); - self.warn_about_dead_assign(expr.span, expr.hir_id, ln, var); + self.warn_about_dead_assign(vec![expr.span], expr.hir_id, ln, var); } } } @@ -1518,109 +1453,112 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } fn warn_about_unused_args(&self, body: &hir::Body, entry_ln: LiveNode) { - for param in &body.params { - param.pat.each_binding(|_bm, hir_id, _, ident| { - let sp = ident.span; - let var = self.variable(hir_id, sp); - // Ignore unused self. - if ident.name != kw::SelfLower { - if !self.warn_about_unused(vec![sp], hir_id, entry_ln, var) { - if self.live_on_entry(entry_ln, var).is_none() { - self.report_dead_assign(hir_id, sp, var, true); - } - } + for p in &body.params { + self.check_unused_vars_in_pat(&p.pat, Some(entry_ln), |spans, hir_id, ln, var| { + if self.live_on_entry(ln, var).is_none() { + self.report_dead_assign(hir_id, spans, var, true); } - }) + }); } } - fn warn_about_unused_or_dead_vars_in_pat(&mut self, pat: &hir::Pat) { - self.pat_bindings(pat, |this, ln, var, sp, id| { - if !this.warn_about_unused(vec![sp], id, ln, var) { - this.warn_about_dead_assign(sp, id, ln, var); + fn check_unused_vars_in_pat( + &self, + pat: &hir::Pat, + entry_ln: Option, + on_used_on_entry: impl Fn(Vec, HirId, LiveNode, Variable), + ) { + // In an or-pattern, only consider the variable; any later patterns must have the same + // bindings, and we also consider the first pattern to be the "authoritative" set of ids. + // However, we should take the spans of variables with the same name from the later + // patterns so the suggestions to prefix with underscores will apply to those too. + let mut vars: FxIndexMap)> = <_>::default(); + + pat.each_binding(|_, hir_id, pat_sp, ident| { + let ln = entry_ln.unwrap_or_else(|| self.live_node(hir_id, pat_sp)); + let var = self.variable(hir_id, ident.span); + vars.entry(self.ir.variable_name(var)) + .and_modify(|(.., spans)| spans.push(ident.span)) + .or_insert_with(|| (ln, var, hir_id, vec![ident.span])); + }); + + for (_, (ln, var, id, spans)) in vars { + if self.used_on_entry(ln, var) { + on_used_on_entry(spans, id, ln, var); + } else { + self.report_unused(spans, id, ln, var); } - }) + } } - fn warn_about_unused(&self, - spans: Vec, - hir_id: HirId, - ln: LiveNode, - var: Variable) - -> bool { - if !self.used_on_entry(ln, var) { - let r = self.should_warn(var); - if let Some(name) = r { - // annoying: for parameters in funcs like `fn(x: i32) - // {ret}`, there is only one node, so asking about - // assigned_on_exit() is not meaningful. - let is_assigned = if ln == self.s.exit_ln { - false - } else { - self.assigned_on_exit(ln, var).is_some() - }; + fn report_unused(&self, spans: Vec, hir_id: HirId, ln: LiveNode, var: Variable) { + if let Some(name) = self.should_warn(var).filter(|name| name != "self") { + // annoying: for parameters in funcs like `fn(x: i32) + // {ret}`, there is only one node, so asking about + // assigned_on_exit() is not meaningful. + let is_assigned = if ln == self.s.exit_ln { + false + } else { + self.assigned_on_exit(ln, var).is_some() + }; - if is_assigned { - self.ir.tcx.lint_hir_note( - lint::builtin::UNUSED_VARIABLES, - hir_id, - spans, - &format!("variable `{}` is assigned to, but never used", name), - &format!("consider using `_{}` instead", name), - ); - } else if name != "self" { - let mut err = self.ir.tcx.struct_span_lint_hir( - lint::builtin::UNUSED_VARIABLES, - hir_id, - spans.clone(), - &format!("unused variable: `{}`", name), - ); + if is_assigned { + self.ir.tcx.lint_hir_note( + lint::builtin::UNUSED_VARIABLES, + hir_id, + spans, + &format!("variable `{}` is assigned to, but never used", name), + &format!("consider using `_{}` instead", name), + ); + } else { + let mut err = self.ir.tcx.struct_span_lint_hir( + lint::builtin::UNUSED_VARIABLES, + hir_id, + spans.clone(), + &format!("unused variable: `{}`", name), + ); + + if self.ir.variable_is_shorthand(var) { + if let Node::Binding(pat) = self.ir.tcx.hir().get(hir_id) { + // Handle `ref` and `ref mut`. + let spans = spans.iter() + .map(|_span| (pat.span, format!("{}: _", name))) + .collect(); - if self.ir.variable_is_shorthand(var) { - if let Node::Binding(pat) = self.ir.tcx.hir().get(hir_id) { - // Handle `ref` and `ref mut`. - let spans = spans.iter() - .map(|_span| (pat.span, format!("{}: _", name))) - .collect(); - - err.multipart_suggestion( - "try ignoring the field", - spans, - Applicability::MachineApplicable, - ); - } - } else { err.multipart_suggestion( - "consider prefixing with an underscore", - spans.iter().map(|span| (*span, format!("_{}", name))).collect(), + "try ignoring the field", + spans, Applicability::MachineApplicable, ); } - - err.emit() + } else { + err.multipart_suggestion( + "consider prefixing with an underscore", + spans.iter().map(|span| (*span, format!("_{}", name))).collect(), + Applicability::MachineApplicable, + ); } + + err.emit() } - true - } else { - false } } - fn warn_about_dead_assign(&self, sp: Span, hir_id: HirId, ln: LiveNode, var: Variable) { + fn warn_about_dead_assign(&self, spans: Vec, hir_id: HirId, ln: LiveNode, var: Variable) { if self.live_on_exit(ln, var).is_none() { - self.report_dead_assign(hir_id, sp, var, false); + self.report_dead_assign(hir_id, spans, var, false); } } - fn report_dead_assign(&self, hir_id: HirId, sp: Span, var: Variable, is_argument: bool) { + fn report_dead_assign(&self, hir_id: HirId, spans: Vec, var: Variable, is_argument: bool) { if let Some(name) = self.should_warn(var) { if is_argument { - self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp, + self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, spans, &format!("value passed to `{}` is never read", name)) .help("maybe it is overwritten before being read?") .emit(); } else { - self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, sp, + self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, spans, &format!("value assigned to `{}` is never read", name)) .help("maybe it is overwritten before being read?") .emit(); From 57eeb61cc861f32351a9d45eed09b6b8ca3c9c5b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 15 Sep 2019 04:07:56 +0200 Subject: [PATCH 039/413] or-patterns: remove `Arm::contains_explicit_ref_binding`. --- src/librustc/hir/pat_util.rs | 17 ----------------- src/librustc_typeck/check/_match.rs | 10 +++++----- 2 files changed, 5 insertions(+), 22 deletions(-) diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index b68886ba62c2d..ea35418bc1ba7 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -189,20 +189,3 @@ impl hir::Pat { result } } - -impl hir::Arm { - /// Checks if the patterns for this arm contain any `ref` or `ref mut` - /// bindings, and if yes whether its containing mutable ones or just immutables ones. - pub fn contains_explicit_ref_binding(&self) -> Option { - // FIXME(tschottdorf): contains_explicit_ref_binding() must be removed - // for #42640 (default match binding modes). - // - // See #44848. - self.top_pats_hack().iter() - .filter_map(|pat| pat.contains_explicit_ref_binding()) - .max_by_key(|m| match *m { - hir::MutMutable => 1, - hir::MutImmutable => 0, - }) - } -} diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 7b971803db599..e0b53525dc90c 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -411,11 +411,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // See #44848. let contains_ref_bindings = arms.iter() - .filter_map(|a| a.contains_explicit_ref_binding()) - .max_by_key(|m| match *m { - hir::MutMutable => 1, - hir::MutImmutable => 0, - }); + .filter_map(|a| a.pat.contains_explicit_ref_binding()) + .max_by_key(|m| match *m { + hir::MutMutable => 1, + hir::MutImmutable => 0, + }); if let Some(m) = contains_ref_bindings { self.check_expr_with_needs(discrim, Needs::maybe_mut_place(m)) From fb2cfec433421ada440a5dc83686f739dc1ab521 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 15 Sep 2019 04:17:55 +0200 Subject: [PATCH 040/413] or-patterns: euv/`arm_move_mode`: remove `top_pats_hack`. --- src/librustc/middle/expr_use_visitor.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index ef84c9bbad60d..0e97a3b59d082 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -779,9 +779,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { fn arm_move_mode(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &hir::Arm) -> TrackMatchMode { let mut mode = Unknown; - for pat in arm.top_pats_hack() { - self.determine_pat_move_mode(discr_cmt.clone(), &pat, &mut mode); - } + self.determine_pat_move_mode(discr_cmt.clone(), &arm.pat, &mut mode); mode } From d7139f3e6d9dfa11d03f8529907d643bbfa8005a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 15 Sep 2019 04:26:00 +0200 Subject: [PATCH 041/413] or-patterns: euv/`walk_arm`: remove `top_pats_hack`. --- src/librustc/middle/expr_use_visitor.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 0e97a3b59d082..a3110c000fb22 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -784,9 +784,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { } fn walk_arm(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &hir::Arm, mode: MatchMode) { - for pat in arm.top_pats_hack() { - self.walk_pat(discr_cmt.clone(), &pat, mode); - } + self.walk_pat(discr_cmt.clone(), &arm.pat, mode); if let Some(hir::Guard::If(ref e)) = arm.guard { self.consume_expr(e) From 07deb93bb291917967d167fa6cdacc62b0186599 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 15 Sep 2019 18:44:32 +0200 Subject: [PATCH 042/413] or-patterns: middle/dead: make a hack less hacky. --- src/librustc/middle/dead.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 666c1cc96f2f7..1818dede3e229 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -260,8 +260,8 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { fn visit_arm(&mut self, arm: &'tcx hir::Arm) { let pats = arm.top_pats_hack(); - if pats.len() == 1 { - let variants = pats[0].necessary_variants(); + if let [pat] = pats { + let variants = pat.necessary_variants(); // Inside the body, ignore constructions of variants // necessary for the pattern to match. Those construction sites From 0dfd706257326cf826cca0a1029cf5bc0c2aee97 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 15 Sep 2019 19:17:21 +0200 Subject: [PATCH 043/413] or-patterns: rvalue_promotion: remove `top_pats_hack`. --- src/librustc_passes/rvalue_promotion.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 7470f5b7a5f0f..12978cd117b52 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -499,19 +499,15 @@ fn check_expr_kind<'a, 'tcx>( } // Conditional control flow (possible to implement). - hir::ExprKind::Match(ref expr, ref hirvec_arm, ref _match_source) => { + hir::ExprKind::Match(ref expr, ref arms, ref _match_source) => { // Compute the most demanding borrow from all the arms' // patterns and set that on the discriminator. - let mut mut_borrow = false; - for pat in hirvec_arm.iter().flat_map(|arm| arm.top_pats_hack()) { - mut_borrow = v.remove_mut_rvalue_borrow(pat); - } - if mut_borrow { + if arms.iter().fold(false, |_, arm| v.remove_mut_rvalue_borrow(&arm.pat)) { v.mut_rvalue_borrows.insert(expr.hir_id); } let _ = v.check_expr(expr); - for index in hirvec_arm.iter() { + for index in arms.iter() { let _ = v.check_expr(&*index.body); if let Some(hir::Guard::If(ref expr)) = index.guard { let _ = v.check_expr(&expr); From 38a5ae9cc1bc2c4fb25a4be639b0eafaeb51426a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 15 Sep 2019 19:24:40 +0200 Subject: [PATCH 044/413] or-patterns: regionck/visit_arm: remove `top_pats_hack`. --- src/librustc_typeck/check/regionck.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 86ec477a6aae8..698b49515fb66 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -488,9 +488,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> { fn visit_arm(&mut self, arm: &'tcx hir::Arm) { // see above - for p in arm.top_pats_hack() { - self.constrain_bindings_in_pat(p); - } + self.constrain_bindings_in_pat(&arm.pat); intravisit::walk_arm(self, arm); } From 9b406f1069852ed2fb6c51e4abb8f51b947c0955 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 15 Sep 2019 19:38:03 +0200 Subject: [PATCH 045/413] or-patterns: regionck/`link_match`: remove `top_pats_hack`. --- src/librustc_typeck/check/regionck.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 698b49515fb66..6fa8a016b5458 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -1067,9 +1067,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { let discr_cmt = Rc::new(ignore_err!(self.with_mc(|mc| mc.cat_expr(discr)))); debug!("discr_cmt={:?}", discr_cmt); for arm in arms { - for root_pat in arm.top_pats_hack() { - self.link_pattern(discr_cmt.clone(), &root_pat); - } + self.link_pattern(discr_cmt.clone(), &arm.pat); } } From 6bd8c6d4f44884a756471dda6ff3e5c66dbbd042 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 15 Sep 2019 19:53:59 +0200 Subject: [PATCH 046/413] or-patterns: check_match: remove `top_pats_hack` for `check_for_bindings_named_same_as_variants`. --- src/librustc_mir/hair/pattern/check_match.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index dc884d40ac157..eb3698957157b 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -146,9 +146,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { } // Third, perform some lints. - for pat in arm.top_pats_hack() { - check_for_bindings_named_same_as_variants(self, pat); - } + check_for_bindings_named_same_as_variants(self, &arm.pat); } let module = self.tcx.hir().get_module_parent(scrut.hir_id); From 549756bef89fa7f9e39cf5e3d04553076ca952ae Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 15 Sep 2019 20:54:38 +0200 Subject: [PATCH 047/413] or-patterns: check_match: nix `top_pats_hack` passed to `check_patterns`. --- src/librustc_mir/hair/pattern/check_match.rs | 70 +++++++++----------- 1 file changed, 30 insertions(+), 40 deletions(-) diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index eb3698957157b..6301d9c390b02 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -14,7 +14,6 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc::hir::def::*; use rustc::hir::def_id::DefId; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; -use rustc::hir::ptr::P; use rustc::hir::{self, Pat, PatKind}; use smallvec::smallvec; @@ -76,7 +75,7 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> { }); // Check legality of move bindings and `@` patterns. - self.check_patterns(false, slice::from_ref(&loc.pat)); + self.check_patterns(false, &loc.pat); } fn visit_body(&mut self, body: &'tcx hir::Body) { @@ -84,7 +83,7 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> { for param in &body.params { self.check_irrefutable(¶m.pat, "function argument"); - self.check_patterns(false, slice::from_ref(¶m.pat)); + self.check_patterns(false, ¶m.pat); } } } @@ -122,11 +121,9 @@ impl PatternContext<'_, '_> { } impl<'tcx> MatchVisitor<'_, 'tcx> { - fn check_patterns(&mut self, has_guard: bool, pats: &[P]) { - check_legality_of_move_bindings(self, has_guard, pats); - for pat in pats { - check_legality_of_bindings_in_at_patterns(self, pat); - } + fn check_patterns(&mut self, has_guard: bool, pat: &Pat) { + check_legality_of_move_bindings(self, has_guard, pat); + check_legality_of_bindings_in_at_patterns(self, pat); } fn check_match( @@ -137,7 +134,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { ) { for arm in arms { // First, check legality of move bindings. - self.check_patterns(arm.guard.is_some(), &arm.top_pats_hack()); + self.check_patterns(arm.guard.is_some(), &arm.pat); // Second, if there is a guard on each arm, make sure it isn't // assigning or borrowing anything mutably. @@ -543,24 +540,18 @@ fn maybe_point_at_variant(ty: Ty<'_>, patterns: &[Pattern<'_>]) -> Vec { covered } -// Legality of move bindings checking -fn check_legality_of_move_bindings( - cx: &mut MatchVisitor<'_, '_>, - has_guard: bool, - pats: &[P], -) { +// Check the legality of legality of by-move bindings. +fn check_legality_of_move_bindings(cx: &mut MatchVisitor<'_, '_>, has_guard: bool, pat: &Pat) { let mut by_ref_span = None; - for pat in pats { - pat.each_binding(|_, hir_id, span, _path| { - if let Some(&bm) = cx.tables.pat_binding_modes().get(hir_id) { - if let ty::BindByReference(..) = bm { - by_ref_span = Some(span); - } - } else { - cx.tcx.sess.delay_span_bug(pat.span, "missing binding mode"); + pat.each_binding(|_, hir_id, span, _| { + if let Some(&bm) = cx.tables.pat_binding_modes().get(hir_id) { + if let ty::BindByReference(..) = bm { + by_ref_span = Some(span); } - }) - } + } else { + cx.tcx.sess.delay_span_bug(pat.span, "missing binding mode"); + } + }); let span_vec = &mut Vec::new(); let mut check_move = |p: &Pat, sub: Option<&Pat>| { @@ -576,23 +567,22 @@ fn check_legality_of_move_bindings( } }; - for pat in pats { - pat.walk(|p| { - if let PatKind::Binding(.., sub) = &p.node { - if let Some(&bm) = cx.tables.pat_binding_modes().get(p.hir_id) { - if let ty::BindByValue(..) = bm { - let pat_ty = cx.tables.node_type(p.hir_id); - if !pat_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, pat.span) { - check_move(p, sub.as_deref()); - } + pat.walk(|p| { + if let PatKind::Binding(.., sub) = &p.node { + if let Some(&bm) = cx.tables.pat_binding_modes().get(p.hir_id) { + if let ty::BindByValue(..) = bm { + let pat_ty = cx.tables.node_type(p.hir_id); + if !pat_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, pat.span) { + check_move(p, sub.as_deref()); } - } else { - cx.tcx.sess.delay_span_bug(pat.span, "missing binding mode"); } + } else { + cx.tcx.sess.delay_span_bug(pat.span, "missing binding mode"); } - true - }); - } + } + true + }); + if !span_vec.is_empty() { let mut err = struct_span_err!( cx.tcx.sess, @@ -603,7 +593,7 @@ fn check_legality_of_move_bindings( if let Some(by_ref_span) = by_ref_span { err.span_label(by_ref_span, "both by-ref and by-move used"); } - for span in span_vec.iter(){ + for span in span_vec.iter() { err.span_label(*span, "by-move pattern here"); } err.emit(); From 68c3739f1268e496c096d89ab9e556f196e35974 Mon Sep 17 00:00:00 2001 From: Tomas Tauber <2410580+tomtau@users.noreply.github.com> Date: Mon, 16 Sep 2019 12:13:02 +0800 Subject: [PATCH 048/413] updated the panic message wording --- src/libstd/thread/local.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index a2bbe371de788..e92c0d1c58e41 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -237,7 +237,7 @@ impl LocalKey { pub fn with(&'static self, f: F) -> R where F: FnOnce(&T) -> R { self.try_with(f).expect("cannot access a Thread Local Storage value \ - during or after it is destroyed") + during or after destruction") } /// Acquires a reference to the value in this TLS key. From 56b055a6abf5f3cf0d4ae13026154eb82298b21b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 16 Sep 2019 03:32:44 +0200 Subject: [PATCH 049/413] or-patterns: HAIR: `Arm.patterns: Vec>` -> `.pattern: Pattern<'_>`. --- src/librustc_mir/build/matches/mod.rs | 6 +++--- src/librustc_mir/hair/cx/expr.rs | 4 ++-- src/librustc_mir/hair/mod.rs | 13 ++++++++++++- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index aa261f8eb6fb2..f23abf86bcfc8 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -142,7 +142,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Step 2. Create the otherwise and prebinding blocks. // create binding start block for link them by false edges - let candidate_count = arms.iter().map(|c| c.patterns.len()).sum::(); + let candidate_count = arms.iter().map(|c| c.top_pats_hack().len()).sum::(); let pre_binding_blocks: Vec<_> = (0..candidate_count) .map(|_| self.cfg.start_new_block()) .collect(); @@ -159,7 +159,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .map(|arm| { let arm_has_guard = arm.guard.is_some(); match_has_guard |= arm_has_guard; - let arm_candidates: Vec<_> = arm.patterns + let arm_candidates: Vec<_> = arm.top_pats_hack() .iter() .zip(candidate_pre_binding_blocks.by_ref()) .map( @@ -238,7 +238,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let scope = this.declare_bindings( None, arm.span, - &arm.patterns[0], + &arm.top_pats_hack()[0], ArmHasGuard(arm.guard.is_some()), Some((Some(&scrutinee_place), scrutinee_span)), ); diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index f3d699fa4f008..bdfcacd0f4629 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -860,9 +860,9 @@ impl ToBorrowKind for hir::Mutability { } } -fn convert_arm<'a, 'tcx>(cx: &mut Cx<'a, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> { +fn convert_arm<'tcx>(cx: &mut Cx<'_, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> { Arm { - patterns: arm.top_pats_hack().iter().map(|p| cx.pattern_from_hir(p)).collect(), + pattern: cx.pattern_from_hir(&arm.pat), guard: match arm.guard { Some(hir::Guard::If(ref e)) => Some(Guard::If(e.to_ref())), _ => None, diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 0638cb462f73b..63a9a83154b4f 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -293,7 +293,7 @@ pub struct FruInfo<'tcx> { #[derive(Clone, Debug)] pub struct Arm<'tcx> { - pub patterns: Vec>, + pub pattern: Pattern<'tcx>, pub guard: Option>, pub body: ExprRef<'tcx>, pub lint_level: LintLevel, @@ -301,6 +301,17 @@ pub struct Arm<'tcx> { pub span: Span, } +impl Arm<'tcx> { + // HACK(or_patterns; Centril | dlrobertson): Remove this and + // correctly handle each case in which this method is used. + pub fn top_pats_hack(&self) -> &[Pattern<'tcx>] { + match &*self.pattern.kind { + PatternKind::Or { pats } => pats, + _ => std::slice::from_ref(&self.pattern), + } + } +} + #[derive(Clone, Debug)] pub enum Guard<'tcx> { If(ExprRef<'tcx>), From 05cc3c0a83fc7faab20a10f2e0eca61dc34a6394 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 16 Sep 2019 16:35:36 +0200 Subject: [PATCH 050/413] or-patterns: liveness: `is_argument` -> `is_param`. Pacify `tidy`. It's also more correct in this context. --- src/librustc/middle/liveness.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 9afd147ae34e2..9f6611712a8aa 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1550,9 +1550,9 @@ impl<'tcx> Liveness<'_, 'tcx> { } } - fn report_dead_assign(&self, hir_id: HirId, spans: Vec, var: Variable, is_argument: bool) { + fn report_dead_assign(&self, hir_id: HirId, spans: Vec, var: Variable, is_param: bool) { if let Some(name) = self.should_warn(var) { - if is_argument { + if is_param { self.ir.tcx.struct_span_lint_hir(lint::builtin::UNUSED_ASSIGNMENTS, hir_id, spans, &format!("value passed to `{}` is never read", name)) .help("maybe it is overwritten before being read?") From 370fbcc0225a226096773fc8641c59eb5e635f7a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 16 Sep 2019 20:49:48 +0200 Subject: [PATCH 051/413] or-patterns: #47390: we rely on names to exercise `IndexMap`. --- ...47390-unused-variable-in-struct-pattern.rs | 3 +++ ...0-unused-variable-in-struct-pattern.stderr | 20 +++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs index 4cb35e907c8f9..7870d394c8bfb 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs @@ -33,6 +33,9 @@ fn main() { let mut mut_unused_var = 1; let (mut var, unused_var) = (1, 2); + // NOTE: `var` comes after `unused_var` lexicographically yet the warning + // for `var` will be emitted before the one for `unused_var`. We use an + // `IndexMap` to ensure this is the case instead of a `BTreeMap`. if let SoulHistory { corridors_of_light, mut hours_are_suns, diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr index a0b34d220c8d9..74bbef8adad05 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr @@ -30,13 +30,13 @@ LL | let (mut var, unused_var) = (1, 2); | ^^^^^^^^^^ help: consider prefixing with an underscore: `_unused_var` warning: unused variable: `corridors_of_light` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:37:26 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:40:26 | LL | if let SoulHistory { corridors_of_light, | ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _` warning: variable `hours_are_suns` is assigned to, but never used - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:38:30 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:41:30 | LL | mut hours_are_suns, | ^^^^^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | mut hours_are_suns, = note: consider using `_hours_are_suns` instead warning: value assigned to `hours_are_suns` is never read - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:40:9 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:43:9 | LL | hours_are_suns = false; | ^^^^^^^^^^^^^^ @@ -58,43 +58,43 @@ LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) = help: maybe it is overwritten before being read? warning: unused variable: `fire` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:44:32 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:47:32 | LL | let LovelyAmbition { lips, fire } = the_spirit; | ^^^^ help: try ignoring the field: `fire: _` warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:53:23 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:56:23 | LL | Large::Suit { case } => {} | ^^^^ help: try ignoring the field: `case: _` warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:58:24 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:61:24 | LL | &Large::Suit { case } => {} | ^^^^ help: try ignoring the field: `case: _` warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:63:27 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:66:27 | LL | box Large::Suit { case } => {} | ^^^^ help: try ignoring the field: `case: _` warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:68:24 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:71:24 | LL | (Large::Suit { case },) => {} | ^^^^ help: try ignoring the field: `case: _` warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:73:24 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:76:24 | LL | [Large::Suit { case }] => {} | ^^^^ help: try ignoring the field: `case: _` warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:78:29 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:81:29 | LL | Tuple(Large::Suit { case }, ()) => {} | ^^^^ help: try ignoring the field: `case: _` From 3f004a1bc44859857f05a9f692a578124b3f3e01 Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Tue, 17 Sep 2019 14:40:36 +0200 Subject: [PATCH 052/413] Fix re-rebalance coherence implementation for fundamental types Fixes #64412 --- src/librustc/traits/coherence.rs | 10 +++++++++- ...pl[t]-foreign[local]-for-fundamental[t].rs | 5 ++--- ...]-foreign[local]-for-fundamental[t].stderr | 19 +++++++++++++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index b6f0addd77107..bc6bcb1f76f96 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -378,7 +378,15 @@ fn orphan_check_trait_ref<'tcx>( // Let Ti be the first such type. // - No uncovered type parameters P1..=Pn may appear in T0..Ti (excluding Ti) // - for input_ty in trait_ref.input_types() { + fn uncover_fundamental_ty(ty: Ty<'_>) -> Vec> { + if fundamental_ty(ty) { + ty.walk_shallow().flat_map(|ty| uncover_fundamental_ty(ty)).collect() + } else { + vec![ty] + } + } + + for input_ty in trait_ref.input_types().flat_map(uncover_fundamental_ty) { debug!("orphan_check_trait_ref: check ty `{:?}`", input_ty); if ty_is_local(tcx, input_ty, in_crate) { debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty); diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs index db671cb9bcaba..54425b6d708aa 100644 --- a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs @@ -2,7 +2,6 @@ // compile-flags:--crate-name=test // aux-build:coherence_lib.rs -// check-pass extern crate coherence_lib as lib; use lib::*; @@ -11,11 +10,11 @@ use std::rc::Rc; struct Local; impl Remote1 for Box { - // FIXME(#64412) -- this is expected to error + //~^ ERROR type parameter `T` must be used as the type parameter for some local type } impl Remote1 for &T { - // FIXME(#64412) -- this is expected to error + //~^ ERROR type parameter `T` must be used as the type parameter for some local type } fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr new file mode 100644 index 0000000000000..7859665a7bb58 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr @@ -0,0 +1,19 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[local]-for-fundamental[t].rs:12:1 + | +LL | impl Remote1 for Box { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[local]-for-fundamental[t].rs:16:1 + | +LL | impl Remote1 for &T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. From a9c38d9d01bd50b5a264cd62fd32cec37f006ab9 Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Wed, 18 Sep 2019 22:14:33 +0200 Subject: [PATCH 053/413] Add more tests --- .../impl-foreign[foreign]-for-foreign.rs | 16 +++++++++++++++ .../impl-foreign[foreign]-for-foreign.stderr | 12 +++++++++++ .../impl-foreign[foreign]-for-local.rs | 16 +++++++++++++++ ...[t]-foreign[foreign]-for-fundamental[t].rs | 20 +++++++++++++++++++ ...foreign[foreign]-for-fundamental[t].stderr | 19 ++++++++++++++++++ .../impl[t]-foreign[foreign]-for-t.rs | 16 +++++++++++++++ .../impl[t]-foreign[foreign]-for-t.stderr | 11 ++++++++++ ...reign[fundamental[t],local]-for-foreign.rs | 20 +++++++++++++++++++ ...n[fundamental[t],local]-for-foreign.stderr | 19 ++++++++++++++++++ ...[t]-foreign[fundamental[t]]-for-foreign.rs | 20 +++++++++++++++++++ ...foreign[fundamental[t]]-for-foreign.stderr | 19 ++++++++++++++++++ ...eign[fundamental[t]]-for-fundamental[t].rs | 19 ++++++++++++++++++ ...[fundamental[t]]-for-fundamental[t].stderr | 19 ++++++++++++++++++ ...pl[t]-foreign[fundamental[t]]-for-local.rs | 17 ++++++++++++++++ .../impl[t]-foreign[fundamental[t]]-for-t.rs | 19 ++++++++++++++++++ ...pl[t]-foreign[fundamental[t]]-for-t.stderr | 19 ++++++++++++++++++ ...eign[local, fundamental[t]]-for-foreign.rs | 19 ++++++++++++++++++ .../impl[t]-foreign[local]-for-foreign.rs | 16 +++++++++++++++ .../impl[t]-foreign[local]-for-local.rs | 15 ++++++++++++++ .../impl[t]-foreign[t]-for-foreign.rs | 16 +++++++++++++++ .../impl[t]-foreign[t]-for-foreign.stderr | 11 ++++++++++ .../impl[t]-foreign[t]-for-fundamental.rs | 20 +++++++++++++++++++ .../impl[t]-foreign[t]-for-fundamental.stderr | 19 ++++++++++++++++++ .../coherence/impl[t]-foreign[t]-for-local.rs | 15 ++++++++++++++ .../ui/coherence/impl[t]-foreign[t]-for-t.rs | 16 +++++++++++++++ .../coherence/impl[t]-foreign[t]-for-t.stderr | 11 ++++++++++ 26 files changed, 439 insertions(+) create mode 100644 src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs create mode 100644 src/test/ui/coherence/impl-foreign[foreign]-for-foreign.stderr create mode 100644 src/test/ui/coherence/impl-foreign[foreign]-for-local.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr create mode 100644 src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr create mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.stderr create mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr create mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr create mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-local.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr create mode 100644 src/test/ui/coherence/impl[t]-foreign[local, fundamental[t]]-for-foreign.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-foreign.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[local]-for-local.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr create mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr create mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-local.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-t.rs create mode 100644 src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr diff --git a/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs b/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs new file mode 100644 index 0000000000000..57738c64e3779 --- /dev/null +++ b/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs @@ -0,0 +1,16 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for f64 { + //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types [E0117] +} + +fn main() {} diff --git a/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.stderr b/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.stderr new file mode 100644 index 0000000000000..04e96f29230fb --- /dev/null +++ b/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.stderr @@ -0,0 +1,12 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/impl-foreign[foreign]-for-foreign.rs:12:1 + | +LL | impl Remote1 for f64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate + | + = note: the impl does not reference only types defined in this crate + = note: define and implement a trait or new type instead + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/src/test/ui/coherence/impl-foreign[foreign]-for-local.rs b/src/test/ui/coherence/impl-foreign[foreign]-for-local.rs new file mode 100644 index 0000000000000..33e85c164763e --- /dev/null +++ b/src/test/ui/coherence/impl-foreign[foreign]-for-local.rs @@ -0,0 +1,16 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Local { +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].rs new file mode 100644 index 0000000000000..66a4d9d273469 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].rs @@ -0,0 +1,20 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Box { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +impl<'a, T> Remote1 for &'a T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr new file mode 100644 index 0000000000000..2467097b1a8b3 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr @@ -0,0 +1,19 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[foreign]-for-fundamental[t].rs:12:1 + | +LL | impl Remote1 for Box { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[foreign]-for-fundamental[t].rs:16:1 + | +LL | impl<'a, T> Remote1 for &'a T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.rs b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.rs new file mode 100644 index 0000000000000..0a67ebcbba44c --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.rs @@ -0,0 +1,16 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr new file mode 100644 index 0000000000000..5c28406f113fc --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr @@ -0,0 +1,11 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[foreign]-for-t.rs:12:1 + | +LL | impl Remote1 for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.rs new file mode 100644 index 0000000000000..24e0f309c4555 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.rs @@ -0,0 +1,20 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote2, Local> for u32 { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +impl<'a, T> Remote2<&'a T, Local> for u32 { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.stderr new file mode 100644 index 0000000000000..da670bcfc3fc9 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.stderr @@ -0,0 +1,19 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t],local]-for-foreign.rs:12:1 + | +LL | impl Remote2, Local> for u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t],local]-for-foreign.rs:16:1 + | +LL | impl<'a, T> Remote2<&'a T, Local> for u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.rs new file mode 100644 index 0000000000000..71598dae96ab3 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.rs @@ -0,0 +1,20 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1> for u32 { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +impl<'a, T> Remote1<&'a T> for u32 { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr new file mode 100644 index 0000000000000..dd9702650795e --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr @@ -0,0 +1,19 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t]]-for-foreign.rs:12:1 + | +LL | impl Remote1> for u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t]]-for-foreign.rs:16:1 + | +LL | impl<'a, T> Remote1<&'a T> for u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs new file mode 100644 index 0000000000000..7bf0306f29ba4 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs @@ -0,0 +1,19 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl<'a, T> Remote1> for &'a T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} +impl<'a, T> Remote1<&'a T> for Box { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr new file mode 100644 index 0000000000000..eec57fccea762 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr @@ -0,0 +1,19 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs:12:1 + | +LL | impl<'a, T> Remote1> for &'a T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t]]-for-fundamental[t].rs:15:1 + | +LL | impl<'a, T> Remote1<&'a T> for Box { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-local.rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-local.rs new file mode 100644 index 0000000000000..54d577c749248 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-local.rs @@ -0,0 +1,17 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1> for Local {} + +impl<'a, T> Remote1<&'a T> for Local {} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.rs new file mode 100644 index 0000000000000..7af929006ef7f --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.rs @@ -0,0 +1,19 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1> for T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} +impl<'a, T> Remote1<&'a T> for T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr new file mode 100644 index 0000000000000..e017c3ffe6c05 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr @@ -0,0 +1,19 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t]]-for-t.rs:12:1 + | +LL | impl Remote1> for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[fundamental[t]]-for-t.rs:15:1 + | +LL | impl<'a, T> Remote1<&'a T> for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[local, fundamental[t]]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[local, fundamental[t]]-for-foreign.rs new file mode 100644 index 0000000000000..be0875d0110fd --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[local, fundamental[t]]-for-foreign.rs @@ -0,0 +1,19 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; +struct Local2(Rc); + +impl Remote2> for u32 {} +impl<'a, T> Remote2 for u32 {} +impl Remote2, Box> for u32 {} +impl<'a, T> Remote2, &'a T> for u32 {} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign.rs new file mode 100644 index 0000000000000..81cf3c3f6eca9 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-foreign.rs @@ -0,0 +1,16 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Rc {} +impl Remote1 for Vec> {} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[local]-for-local.rs b/src/test/ui/coherence/impl[t]-foreign[local]-for-local.rs new file mode 100644 index 0000000000000..6b1d93cd94442 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[local]-for-local.rs @@ -0,0 +1,15 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Local {} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.rs new file mode 100644 index 0000000000000..5e89c2077330a --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.rs @@ -0,0 +1,16 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for u32 { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr b/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr new file mode 100644 index 0000000000000..5544729b5d640 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-foreign.stderr @@ -0,0 +1,11 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[t]-for-foreign.rs:12:1 + | +LL | impl Remote1 for u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.rs b/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.rs new file mode 100644 index 0000000000000..300a2c4d48a9c --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.rs @@ -0,0 +1,20 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Box { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +impl<'a, A, B> Remote1
    for &'a B { + //~^ ERROR type parameter `B` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr b/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr new file mode 100644 index 0000000000000..be8cc29a6e5b0 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-fundamental.stderr @@ -0,0 +1,19 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[t]-for-fundamental.rs:12:1 + | +LL | impl Remote1 for Box { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error[E0210]: type parameter `B` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[t]-for-fundamental.rs:16:1 + | +LL | impl<'a, A, B> Remote1 for &'a B { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `B` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-local.rs b/src/test/ui/coherence/impl[t]-foreign[t]-for-local.rs new file mode 100644 index 0000000000000..769147ea7eabd --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-local.rs @@ -0,0 +1,15 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs +// check-pass + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for Local {} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-t.rs b/src/test/ui/coherence/impl[t]-foreign[t]-for-t.rs new file mode 100644 index 0000000000000..c8513380ff73e --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-t.rs @@ -0,0 +1,16 @@ +#![feature(re_rebalance_coherence)] + +// compile-flags:--crate-name=test +// aux-build:coherence_lib.rs + +extern crate coherence_lib as lib; +use lib::*; +use std::rc::Rc; + +struct Local; + +impl Remote1 for T { + //~^ ERROR type parameter `T` must be used as the type parameter for some local type +} + +fn main() {} diff --git a/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr b/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr new file mode 100644 index 0000000000000..de857afd20b15 --- /dev/null +++ b/src/test/ui/coherence/impl[t]-foreign[t]-for-t.stderr @@ -0,0 +1,11 @@ +error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) + --> $DIR/impl[t]-foreign[t]-for-t.rs:12:1 + | +LL | impl Remote1 for T { + | ^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type + | + = note: only traits defined in the current crate can be implemented for a type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0210`. From 31b301219f534090690674e43e05c3cbfd2d5005 Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Wed, 18 Sep 2019 22:36:04 +0200 Subject: [PATCH 054/413] Split line to fix tidy --- src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs b/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs index 57738c64e3779..b08fedc5e11c2 100644 --- a/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs +++ b/src/test/ui/coherence/impl-foreign[foreign]-for-foreign.rs @@ -10,7 +10,8 @@ use std::rc::Rc; struct Local; impl Remote1 for f64 { - //~^ ERROR only traits defined in the current crate can be implemented for arbitrary types [E0117] + //~^ ERROR only traits defined in the current crate + // | can be implemented for arbitrary types [E0117] } fn main() {} From 25211894386a34db1639fbd69680e8f7b35ee1a4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 30 Aug 2019 17:27:35 +1000 Subject: [PATCH 055/413] Add a comment to `Compiler::compile()`. `Compiler::compile()` is different to all the other `Compiler` methods because it lacks a `Queries` entry. It only has one call site, which is in a test that doesn't need its specific characteristics. This patch replaces that call with a call to `Compile::link()`, which is similar enough for the test's purposes. It also notes that the method is an illustrative example of how `Compiler` can be used. --- src/librustc_interface/queries.rs | 9 +++++++-- src/test/run-make-fulldeps/issue-19371/foo.rs | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index e056d3feb66ec..ff5cd8b8c695d 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -275,6 +275,11 @@ impl Compiler { }) } + // This method is different to all the other methods in `Compiler` because + // it lacks a `Queries` entry. It's also not currently used. It does serve + // as an example of how `Compiler` can be used, with additional steps added + // between some passes. And see `rustc_driver::run_compiler` for a more + // complex example. pub fn compile(&self) -> Result<()> { self.prepare_outputs()?; @@ -286,12 +291,12 @@ impl Compiler { self.global_ctxt()?; - // Drop AST after creating GlobalCtxt to free memory + // Drop AST after creating GlobalCtxt to free memory. mem::drop(self.expansion()?.take()); self.ongoing_codegen()?; - // Drop GlobalCtxt after starting codegen to free memory + // Drop GlobalCtxt after starting codegen to free memory. mem::drop(self.global_ctxt()?.take()); self.link().map(|_| ()) diff --git a/src/test/run-make-fulldeps/issue-19371/foo.rs b/src/test/run-make-fulldeps/issue-19371/foo.rs index afc92638fda97..e290f7fa6b13a 100644 --- a/src/test/run-make-fulldeps/issue-19371/foo.rs +++ b/src/test/run-make-fulldeps/issue-19371/foo.rs @@ -62,6 +62,7 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) { }; interface::run_compiler(config, |compiler| { - compiler.compile().ok(); + // This runs all the passes prior to linking, too. + compiler.link().ok(); }); } From 2fd4c27c329d85a69a6b585d217e48b4d500477e Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 19 Sep 2019 03:02:08 +0000 Subject: [PATCH 056/413] add is_async_fn query --- src/librustc/query/mod.rs | 4 ++++ src/librustc_metadata/cstore_impl.rs | 1 + src/librustc_metadata/decoder.rs | 9 +++++++++ src/librustc_metadata/encoder.rs | 4 ++++ src/librustc_metadata/schema.rs | 1 + 5 files changed, 19 insertions(+) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index c7260945295a6..c4f62df12b766 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -244,6 +244,10 @@ rustc_queries! { desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) } } + query is_async_fn(key: DefId) -> hir::IsAsync { + desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) } + } + /// Returns `true` if calls to the function may be promoted. /// /// This is either because the function is e.g., a tuple-struct or tuple-variant diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index a1e3bbcbf8ea9..6db3bfd8880ff 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -133,6 +133,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, fn_sig => { cdata.fn_sig(def_id.index, tcx) } inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } is_const_fn_raw => { cdata.is_const_fn_raw(def_id.index) } + is_async_fn { cdata.fn_asyncness(def_id.index) } is_foreign_item => { cdata.is_foreign_item(def_id.index) } static_mutability => { cdata.static_mutability(def_id.index) } def_kind => { cdata.def_kind(def_id.index) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 75d7261704722..6cc5c409e1331 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1208,6 +1208,15 @@ impl<'a, 'tcx> CrateMetadata { constness == hir::Constness::Const } + pub fn is_async_fn(&self, id: DefIndex) -> bool { + let asyncness = match self.entry(id).kind { + EntryKind::Fn(data) => data.decode(self).asyncness, + EntryKind::Method(data) => data.decode(self).fn_data.asyncness, + _ => hir::IsAsync::NotAsync, + }; + asyncness == hir::IsAsync::Async + } + pub fn is_foreign_item(&self, id: DefIndex) -> bool { match self.entry(id).kind { EntryKind::ForeignImmStatic | diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index f430f01542efe..439763810ec0e 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -885,6 +885,7 @@ impl EncodeContext<'tcx> { } }; FnData { + asyncness: hir::IsAsync::NotAsync, constness: hir::Constness::NotConst, param_names, sig: self.lazy(&tcx.fn_sig(def_id)), @@ -982,6 +983,7 @@ impl EncodeContext<'tcx> { ty::AssocKind::Method => { let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node { FnData { + asyncness: sig.header.asyncness, constness: sig.header.constness, param_names: self.encode_fn_param_names_for_body(body), sig: self.lazy(&tcx.fn_sig(def_id)), @@ -1128,6 +1130,7 @@ impl EncodeContext<'tcx> { } hir::ItemKind::Fn(_, header, .., body) => { let data = FnData { + asyncness: header.asyncness, constness: header.constness, param_names: self.encode_fn_param_names_for_body(body), sig: self.lazy(tcx.fn_sig(def_id)), @@ -1675,6 +1678,7 @@ impl EncodeContext<'tcx> { let kind = match nitem.node { hir::ForeignItemKind::Fn(_, ref names, _) => { let data = FnData { + asyncness: hir::IsAsync::NotAsync, constness: hir::Constness::NotConst, param_names: self.encode_fn_param_names(names), sig: self.lazy(tcx.fn_sig(def_id)), diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 1a5f0e17ba7ce..92534ab056a8b 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -295,6 +295,7 @@ pub struct MacroDef { #[derive(RustcEncodable, RustcDecodable)] pub struct FnData<'tcx> { + pub asyncness: hir::IsAsync, pub constness: hir::Constness, pub param_names: Lazy<[ast::Name]>, pub sig: Lazy>, From 9ffb1ce28cb1656d6142f1f9f6f882eb187fac25 Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 19 Sep 2019 03:21:11 +0000 Subject: [PATCH 057/413] append asyncness info to functions --- src/librustc/query/mod.rs | 2 +- src/librustc/ty/mod.rs | 15 +++++++++++++++ src/librustc_metadata/cstore_impl.rs | 2 +- src/librustc_metadata/encoder.rs | 4 ++-- src/librustdoc/clean/inline.rs | 8 ++++++-- src/librustdoc/clean/mod.rs | 7 ++++++- 6 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index c4f62df12b766..5e1db92b55580 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -244,7 +244,7 @@ rustc_queries! { desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) } } - query is_async_fn(key: DefId) -> hir::IsAsync { + query is_async_fn(key: DefId) -> bool { desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 5ca819e12f232..97981f4782003 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3349,6 +3349,20 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { } } +fn is_async_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) { + let node = tcx.hir().get(hir_id); + if let Some(fn_like) = hir::map::blocks::FnLikeNode::from_node(node) { + fn_like.asyncness() == hir::IsAsync::Async + } else { + false + } + } else { + false + } +} + + pub fn provide(providers: &mut ty::query::Providers<'_>) { context::provide(providers); erase_regions::provide(providers); @@ -3356,6 +3370,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { util::provide(providers); constness::provide(providers); *providers = ty::query::Providers { + is_async_fn, associated_item, associated_item_def_ids, adt_sized_constraint, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 6db3bfd8880ff..c46e2a901f88d 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -133,7 +133,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, fn_sig => { cdata.fn_sig(def_id.index, tcx) } inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } is_const_fn_raw => { cdata.is_const_fn_raw(def_id.index) } - is_async_fn { cdata.fn_asyncness(def_id.index) } + is_async_fn => { cdata.is_async_fn(def_id.index) } is_foreign_item => { cdata.is_foreign_item(def_id.index) } static_mutability => { cdata.static_mutability(def_id.index) } def_kind => { cdata.def_kind(def_id.index) } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 439763810ec0e..1e7c0829a26a9 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -875,7 +875,7 @@ impl EncodeContext<'tcx> { EntryKind::AssocConst(container, const_qualif, rendered_const) } ty::AssocKind::Method => { - let fn_data = if let hir::TraitItemKind::Method(_, ref m) = ast_item.node { + let fn_data = if let hir::TraitItemKind::Method(method_sig, m) = &ast_item.node { let param_names = match *m { hir::TraitMethod::Required(ref names) => { self.encode_fn_param_names(names) @@ -885,7 +885,7 @@ impl EncodeContext<'tcx> { } }; FnData { - asyncness: hir::IsAsync::NotAsync, + asyncness: method_sig.header.asyncness, constness: hir::Constness::NotConst, param_names, sig: self.lazy(&tcx.fn_sig(def_id)), diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index cb42ff1c8052f..0752934c8c1de 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -217,7 +217,11 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function { } else { hir::Constness::NotConst }; - + let asyncness = if cx.tcx.is_async_fn(did) { + hir::IsAsync::Async + } else { + hir::IsAsync::NotAsync + }; let predicates = cx.tcx.predicates_of(did); let (generics, decl) = clean::enter_impl_trait(cx, || { ((cx.tcx.generics_of(did), &predicates).clean(cx), (did, sig).clean(cx)) @@ -230,7 +234,7 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function { unsafety: sig.unsafety(), abi: sig.abi(), constness, - asyncness: hir::IsAsync::NotAsync, + asyncness, }, all_types, ret_types, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ae70fdc530be6..7bd54c64cf6f5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2403,6 +2403,11 @@ impl Clean for ty::AssocItem { } else { hir::Constness::NotConst }; + let asyncness = if cx.tcx.is_async_fn(self.def_id) { + hir::IsAsync::Async + } else { + hir::IsAsync::NotAsync + }; let defaultness = match self.container { ty::ImplContainer(_) => Some(self.defaultness), ty::TraitContainer(_) => None, @@ -2414,7 +2419,7 @@ impl Clean for ty::AssocItem { unsafety: sig.unsafety(), abi: sig.abi(), constness, - asyncness: hir::IsAsync::NotAsync, + asyncness, }, defaultness, all_types, From aaff05bd1c420a46c91f61f83c256b9f83605c43 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 19 Sep 2019 16:51:41 +1000 Subject: [PATCH 058/413] Reorder the state handling in `process_cycles()`. This gives a slight speed-up. --- .../obligation_forest/mod.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs index 98ae1a5832447..37f4537f4b770 100644 --- a/src/librustc_data_structures/obligation_forest/mod.rs +++ b/src/librustc_data_structures/obligation_forest/mod.rs @@ -484,13 +484,16 @@ impl ObligationForest { debug!("process_cycles()"); for (index, node) in self.nodes.iter().enumerate() { - // For rustc-benchmarks/inflate-0.1.0 this state test is extremely - // hot and the state is almost always `Pending` or `Waiting`. It's - // a win to handle the no-op cases immediately to avoid the cost of - // the function call. + // For some benchmarks this state test is extremely + // hot. It's a win to handle the no-op cases immediately to avoid + // the cost of the function call. match node.state.get() { - NodeState::Waiting | NodeState::Pending | NodeState::Done | NodeState::Error => {}, - _ => self.find_cycles_from_node(&mut stack, processor, index), + // Match arms are in order of frequency. Pending, Success and + // Waiting dominate; the others are rare. + NodeState::Pending => {}, + NodeState::Success => self.find_cycles_from_node(&mut stack, processor, index), + NodeState::Waiting | NodeState::Done | NodeState::Error => {}, + NodeState::OnDfsStack => self.find_cycles_from_node(&mut stack, processor, index), } } From acf7d4dcdba4046917c61aab141c1dec25669ce9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 18 Sep 2019 14:50:48 +1000 Subject: [PATCH 059/413] Specialize the `stalled_on` handling in `process_obligation()`. Optimizing for the common numbers of entries in `stalled_on` wins about 4% on `keccak` and `inflate`. --- src/librustc/infer/mod.rs | 4 +-- src/librustc/traits/fulfill.rs | 55 ++++++++++++++++++++++------------ 2 files changed, 38 insertions(+), 21 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index c5712cc9941a9..eaef2198e3bcf 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1600,8 +1600,8 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> { // `resolver.shallow_resolve_changed(ty)` is equivalent to // `resolver.shallow_resolve(ty) != ty`, but more efficient. It's always - // inlined, despite being large, because it has a single call site that is - // extremely hot. + // inlined, despite being large, because it has only two call sites that + // are extremely hot. #[inline(always)] pub fn shallow_resolve_changed(&mut self, typ: Ty<'tcx>) -> bool { match typ.sty { diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 805727b6ce0d7..6c421e9df6800 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -256,29 +256,46 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { &mut self, pending_obligation: &mut Self::Obligation, ) -> ProcessResult { - // If we were stalled on some unresolved variables, first check - // whether any of them have been resolved; if not, don't bother - // doing more work yet - if !pending_obligation.stalled_on.is_empty() { - let mut changed = false; - // This `for` loop was once a call to `all()`, but this lower-level - // form was a perf win. See #64545 for details. - for &ty in &pending_obligation.stalled_on { - if ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(ty) { - changed = true; - break; - } + // If we were stalled on some unresolved variables, first check whether + // any of them have been resolved; if not, don't bother doing more work + // yet. + let change = match pending_obligation.stalled_on.len() { + // Match arms are in order of frequency, which matters because this + // code is so hot. 1 and 0 dominate; 2+ is fairly rare. + 1 => { + let ty = pending_obligation.stalled_on[0]; + ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(ty) + } + 0 => { + // In this case we haven't changed, but wish to make a change. + true } - if !changed { - debug!("process_predicate: pending obligation {:?} still stalled on {:?}", - self.selcx.infcx() - .resolve_vars_if_possible(&pending_obligation.obligation), - pending_obligation.stalled_on); - return ProcessResult::Unchanged; + _ => { + // This `for` loop was once a call to `all()`, but this lower-level + // form was a perf win. See #64545 for details. + (|| { + for &ty in &pending_obligation.stalled_on { + if ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(ty) { + return true; + } + } + false + })() } - pending_obligation.stalled_on = vec![]; + }; + + if !change { + debug!("process_predicate: pending obligation {:?} still stalled on {:?}", + self.selcx.infcx() + .resolve_vars_if_possible(&pending_obligation.obligation), + pending_obligation.stalled_on); + return ProcessResult::Unchanged; } + // This part of the code is much colder. + + pending_obligation.stalled_on.truncate(0); + let obligation = &mut pending_obligation.obligation; if obligation.predicate.has_infer_types() { From 3eae7f6291677fea37bcf91fd42e435803eabebf Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 20 Sep 2019 11:23:47 +1000 Subject: [PATCH 060/413] Upgrade to ena-0.13.1 and use the new `inlined_probe_value` function. This is a big speed win for `keccak` and `inflate`. --- Cargo.lock | 4 ++-- src/librustc/infer/mod.rs | 5 +++-- src/librustc/infer/type_variable.rs | 8 +++++++- src/librustc_data_structures/Cargo.toml | 2 +- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f52e9738da8f9..78de3af2631d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -910,9 +910,9 @@ dependencies = [ [[package]] name = "ena" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dc01d68e08ca384955a3aeba9217102ca1aa85b6e168639bf27739f1d749d87" +checksum = "8944dc8fa28ce4a38f778bd46bf7d923fe73eed5a439398507246c8e017e6f36" dependencies = [ "log", ] diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index eaef2198e3bcf..5d556485c15f3 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1609,20 +1609,21 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> { use self::type_variable::TypeVariableValue; // See the comment in `shallow_resolve()`. - match self.infcx.type_variables.borrow_mut().probe(v) { + match self.infcx.type_variables.borrow_mut().inlined_probe(v) { TypeVariableValue::Known { value: t } => self.fold_ty(t) != typ, TypeVariableValue::Unknown { .. } => false, } } ty::Infer(ty::IntVar(v)) => { - match self.infcx.int_unification_table.borrow_mut().probe_value(v) { + match self.infcx.int_unification_table.borrow_mut().inlined_probe_value(v) { Some(v) => v.to_type(self.infcx.tcx) != typ, None => false, } } ty::Infer(ty::FloatVar(v)) => { + // Not `inlined_probe_value(v)` because this call site is colder. match self.infcx.float_unification_table.borrow_mut().probe_value(v) { Some(v) => v.to_type(self.infcx.tcx) != typ, None => false, diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index e30e86998a8c6..dd09e9a8f58a4 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -234,7 +234,13 @@ impl<'tcx> TypeVariableTable<'tcx> { /// Retrieves the type to which `vid` has been instantiated, if /// any. pub fn probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> { - self.eq_relations.probe_value(vid) + self.inlined_probe(vid) + } + + /// An always-inlined variant of `probe`, for very hot call sites. + #[inline(always)] + pub fn inlined_probe(&mut self, vid: ty::TyVid) -> TypeVariableValue<'tcx> { + self.eq_relations.inlined_probe_value(vid) } /// If `t` is a type-inference variable, and it has been diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index be9f79c83bb5a..ae3403cf0ce9f 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -10,7 +10,7 @@ path = "lib.rs" doctest = false [dependencies] -ena = "0.13" +ena = "0.13.1" indexmap = "1" log = "0.4" jobserver_crate = { version = "0.1.13", package = "jobserver" } From 8d73faf9ab471ffa927360040247deb082a65a43 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 20 Sep 2019 11:25:16 +1000 Subject: [PATCH 061/413] Remove some unnecessary `backtrace` intermediate variables. --- src/librustc_data_structures/obligation_forest/mod.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs index 37f4537f4b770..bcd041afc055c 100644 --- a/src/librustc_data_structures/obligation_forest/mod.rs +++ b/src/librustc_data_structures/obligation_forest/mod.rs @@ -355,10 +355,9 @@ impl ObligationForest { let mut errors = vec![]; for (index, node) in self.nodes.iter().enumerate() { if let NodeState::Pending = node.state.get() { - let backtrace = self.error_at(index); errors.push(Error { error: error.clone(), - backtrace, + backtrace: self.error_at(index), }); } } @@ -439,10 +438,9 @@ impl ObligationForest { } ProcessResult::Error(err) => { stalled = false; - let backtrace = self.error_at(index); errors.push(Error { error: err, - backtrace, + backtrace: self.error_at(index), }); } } From 75fd4f754e344df63353eb530f31500455b904d8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 20 Sep 2019 11:26:07 +1000 Subject: [PATCH 062/413] Rename a loop variable. We normally use `index` for indices to `ObligationForest::nodes`, but this is a `Nodes::dependents` index. --- .../obligation_forest/mod.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs index bcd041afc055c..be8245e158e3d 100644 --- a/src/librustc_data_structures/obligation_forest/mod.rs +++ b/src/librustc_data_structures/obligation_forest/mod.rs @@ -698,18 +698,18 @@ impl ObligationForest { let nodes_len = node_rewrites.len(); for node in &mut self.nodes { - let mut index = 0; - while index < node.dependents.len() { - let new_index = node_rewrites[node.dependents[index]]; + let mut i = 0; + while i < node.dependents.len() { + let new_index = node_rewrites[node.dependents[i]]; if new_index >= nodes_len { - node.dependents.swap_remove(index); - if index == 0 && node.has_parent { + node.dependents.swap_remove(i); + if i == 0 && node.has_parent { // We just removed the parent. node.has_parent = false; } } else { - node.dependents[index] = new_index; - index += 1; + node.dependents[i] = new_index; + i += 1; } } } From 27c7c23840290fed94aef069b47169b26b7c3625 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 20 Sep 2019 11:29:45 +1000 Subject: [PATCH 063/413] Rename `waiting_cache`. The name `waiting_cache` sounds like it is related to the states `NodeState::Waiting`, but it's not; the cache holds nodes of various states. This commit changes it to `active_state`. --- .../obligation_forest/mod.rs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs index be8245e158e3d..2b7c44cdac35b 100644 --- a/src/librustc_data_structures/obligation_forest/mod.rs +++ b/src/librustc_data_structures/obligation_forest/mod.rs @@ -149,7 +149,7 @@ pub struct ObligationForest { /// A cache of the nodes in `nodes`, indexed by predicate. Unfortunately, /// its contents are not guaranteed to match those of `nodes`. See the /// comments in `process_obligation` for details. - waiting_cache: FxHashMap, + active_cache: FxHashMap, /// A scratch vector reused in various operations, to avoid allocating new /// vectors. @@ -278,7 +278,7 @@ impl ObligationForest { ObligationForest { nodes: vec![], done_cache: Default::default(), - waiting_cache: Default::default(), + active_cache: Default::default(), scratch: RefCell::new(vec![]), obligation_tree_id_generator: (0..).map(ObligationTreeId), error_cache: Default::default(), @@ -303,15 +303,15 @@ impl ObligationForest { return Ok(()); } - match self.waiting_cache.entry(obligation.as_predicate().clone()) { + match self.active_cache.entry(obligation.as_predicate().clone()) { Entry::Occupied(o) => { debug!("register_obligation_at({:?}, {:?}) - duplicate of {:?}!", obligation, parent, o.get()); let node = &mut self.nodes[*o.get()]; if let Some(parent_index) = parent { - // If the node is already in `waiting_cache`, it has - // already had its chance to be marked with a parent. So if - // it's not already present, just dump `parent` into the + // If the node is already in `active_cache`, it has already + // had its chance to be marked with a parent. So if it's + // not already present, just dump `parent` into the // dependents as a non-parent. if !node.dependents.contains(&parent_index) { node.dependents.push(parent_index); @@ -405,8 +405,8 @@ impl ObligationForest { // `processor.process_obligation` can modify the predicate within // `node.obligation`, and that predicate is the key used for - // `self.waiting_cache`. This means that `self.waiting_cache` can - // get out of sync with `nodes`. It's not very common, but it does + // `self.active_cache`. This means that `self.active_cache` can get + // out of sync with `nodes`. It's not very common, but it does // happen, and code in `compress` has to allow for it. let result = match node.state.get() { NodeState::Pending => processor.process_obligation(&mut node.obligation), @@ -637,11 +637,11 @@ impl ObligationForest { } NodeState::Done => { // This lookup can fail because the contents of - // `self.waiting_cache` is not guaranteed to match those of + // `self.active_cache` is not guaranteed to match those of // `self.nodes`. See the comment in `process_obligation` // for more details. - if let Some((predicate, _)) = self.waiting_cache - .remove_entry(node.obligation.as_predicate()) + if let Some((predicate, _)) = + self.active_cache.remove_entry(node.obligation.as_predicate()) { self.done_cache.insert(predicate); } else { @@ -654,7 +654,7 @@ impl ObligationForest { // We *intentionally* remove the node from the cache at this point. Otherwise // tests must come up with a different type on every type error they // check against. - self.waiting_cache.remove(node.obligation.as_predicate()); + self.active_cache.remove(node.obligation.as_predicate()); node_rewrites[index] = nodes_len; dead_nodes += 1; self.insert_into_error_cache(index); @@ -714,9 +714,9 @@ impl ObligationForest { } } - // This updating of `self.waiting_cache` is necessary because the + // This updating of `self.active_cache` is necessary because the // removal of nodes within `compress` can fail. See above. - self.waiting_cache.retain(|_predicate, index| { + self.active_cache.retain(|_predicate, index| { let new_index = node_rewrites[*index]; if new_index >= nodes_len { false From aa10abb2119f0740aac704a78d6eebd800ddb1da Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 20 Sep 2019 12:53:22 +1000 Subject: [PATCH 064/413] Rename a variable. Because the meaning of this `index` variable is quite different to all the other `index` variables in this file. --- src/librustc_data_structures/obligation_forest/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs index 2b7c44cdac35b..1c7109fe500e0 100644 --- a/src/librustc_data_structures/obligation_forest/mod.rs +++ b/src/librustc_data_structures/obligation_forest/mod.rs @@ -507,8 +507,8 @@ impl ObligationForest { let node = &self.nodes[index]; match node.state.get() { NodeState::OnDfsStack => { - let index = stack.iter().rposition(|&n| n == index).unwrap(); - processor.process_backedge(stack[index..].iter().map(GetObligation(&self.nodes)), + let rpos = stack.iter().rposition(|&n| n == index).unwrap(); + processor.process_backedge(stack[rpos..].iter().map(GetObligation(&self.nodes)), PhantomData); } NodeState::Success => { From a813cc1bf190f9cdcd7dce2eba287c637ce4048f Mon Sep 17 00:00:00 2001 From: csmoe Date: Sat, 21 Sep 2019 03:17:57 +0000 Subject: [PATCH 065/413] rename is_async_fn to asyncness --- src/librustc/query/mod.rs | 2 +- src/librustc/ty/mod.rs | 11 ++++++----- src/librustc_metadata/cstore_impl.rs | 2 +- src/librustc_metadata/decoder.rs | 7 +++---- src/librustdoc/clean/inline.rs | 6 +----- src/librustdoc/clean/mod.rs | 6 +----- 6 files changed, 13 insertions(+), 21 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 5e1db92b55580..252e49d5d15f6 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -244,7 +244,7 @@ rustc_queries! { desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) } } - query is_async_fn(key: DefId) -> bool { + query asyncness(key: DefId) -> hir::IsAsync { desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 97981f4782003..dd36a4520929a 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3349,16 +3349,17 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { } } -fn is_async_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { +/// Check if a function is async. +fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) { let node = tcx.hir().get(hir_id); if let Some(fn_like) = hir::map::blocks::FnLikeNode::from_node(node) { - fn_like.asyncness() == hir::IsAsync::Async + fn_like.asyncness() } else { - false + hir::IsAsync::NotAsync } } else { - false + hir::IsAsync::NotAsync } } @@ -3370,7 +3371,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { util::provide(providers); constness::provide(providers); *providers = ty::query::Providers { - is_async_fn, + asyncness, associated_item, associated_item_def_ids, adt_sized_constraint, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index c46e2a901f88d..55cf3965aa85a 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -133,7 +133,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, fn_sig => { cdata.fn_sig(def_id.index, tcx) } inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } is_const_fn_raw => { cdata.is_const_fn_raw(def_id.index) } - is_async_fn => { cdata.is_async_fn(def_id.index) } + asyncness => { cdata.asyncness(def_id.index) } is_foreign_item => { cdata.is_foreign_item(def_id.index) } static_mutability => { cdata.static_mutability(def_id.index) } def_kind => { cdata.def_kind(def_id.index) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 6cc5c409e1331..5153564fc8255 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1208,13 +1208,12 @@ impl<'a, 'tcx> CrateMetadata { constness == hir::Constness::Const } - pub fn is_async_fn(&self, id: DefIndex) -> bool { - let asyncness = match self.entry(id).kind { + pub fn asyncness(&self, id: DefIndex) -> hir::IsAsync { + match self.entry(id).kind { EntryKind::Fn(data) => data.decode(self).asyncness, EntryKind::Method(data) => data.decode(self).fn_data.asyncness, _ => hir::IsAsync::NotAsync, - }; - asyncness == hir::IsAsync::Async + } } pub fn is_foreign_item(&self, id: DefIndex) -> bool { diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 0752934c8c1de..d71acb4fa7b31 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -217,11 +217,7 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function { } else { hir::Constness::NotConst }; - let asyncness = if cx.tcx.is_async_fn(did) { - hir::IsAsync::Async - } else { - hir::IsAsync::NotAsync - }; + let asyncness = cx.tcx.asyncness(did); let predicates = cx.tcx.predicates_of(did); let (generics, decl) = clean::enter_impl_trait(cx, || { ((cx.tcx.generics_of(did), &predicates).clean(cx), (did, sig).clean(cx)) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7bd54c64cf6f5..95a5869e84510 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2403,11 +2403,7 @@ impl Clean for ty::AssocItem { } else { hir::Constness::NotConst }; - let asyncness = if cx.tcx.is_async_fn(self.def_id) { - hir::IsAsync::Async - } else { - hir::IsAsync::NotAsync - }; + let asyncness = cx.tcx.asyncness(self.def_id); let defaultness = match self.container { ty::ImplContainer(_) => Some(self.defaultness), ty::TraitContainer(_) => None, From 726fe3b25573c8406a74e751d54f0bd3c663ea03 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sat, 21 Sep 2019 08:14:41 +0000 Subject: [PATCH 066/413] add rustdoc test for async fn reexport --- .../rustdoc/inline_cross/auxiliary/impl_trait_aux.rs | 10 ++++++++++ src/test/rustdoc/inline_cross/impl_trait.rs | 10 +++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs b/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs index 21c733a9bc98e..913ba8f2a1649 100644 --- a/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs +++ b/src/test/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs @@ -1,3 +1,5 @@ +// edition:2018 + use std::ops::Deref; pub fn func<'a>(_x: impl Clone + Into> + 'a) {} @@ -11,8 +13,16 @@ pub fn func3(_x: impl Iterator> + Clone) {} pub fn func4>(_x: T) {} +pub async fn async_fn() {} + pub struct Foo; impl Foo { pub fn method<'a>(_x: impl Clone + Into> + 'a) {} } + +pub struct Bar; + +impl Bar { + pub async fn async_foo(&self) {} +} diff --git a/src/test/rustdoc/inline_cross/impl_trait.rs b/src/test/rustdoc/inline_cross/impl_trait.rs index b1e3f8d145b5f..6f4a48c83c05b 100644 --- a/src/test/rustdoc/inline_cross/impl_trait.rs +++ b/src/test/rustdoc/inline_cross/impl_trait.rs @@ -1,4 +1,5 @@ // aux-build:impl_trait_aux.rs +// edition:2018 extern crate impl_trait_aux; @@ -20,13 +21,20 @@ pub use impl_trait_aux::func2; // @!has - '//pre[@class="rust fn"]' 'where' pub use impl_trait_aux::func3; - // @has impl_trait/fn.func4.html // @has - '//pre[@class="rust fn"]' "func4(" // @has - '//pre[@class="rust fn"]' "T: Iterator," pub use impl_trait_aux::func4; +// @has impl_trait/fn.async_fn.html +// @has - '//pre[@class="rust fn"]' "pub async fn async_fn()" +pub use impl_trait_aux::async_fn; + // @has impl_trait/struct.Foo.html // @has - '//code[@id="method.v"]' "pub fn method<'a>(_x: impl Clone + Into> + 'a)" // @!has - '//code[@id="method.v"]' 'where' pub use impl_trait_aux::Foo; + +// @has impl_trait/struct.Bar.html +// @has - '//*[@id="method.async_foo"]' "pub async fn async_foo(" +pub use impl_trait_aux::Bar; From 0918dc4e5990592c28484d1d64bec41cb9a4a301 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 21 Sep 2019 15:49:15 +0200 Subject: [PATCH 067/413] or-patterns: middle/dead: remove `top_pats_hack`. Also tweak walkers on `Pat`. --- src/librustc/hir/mod.rs | 62 ++++++++++++------- src/librustc/hir/pat_util.rs | 112 ++++++++++++++++------------------- src/librustc/middle/dead.rs | 21 +++---- 3 files changed, 100 insertions(+), 95 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index edb55ab3caaf4..87fc385acd64d 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -882,39 +882,61 @@ impl fmt::Debug for Pat { impl Pat { // FIXME(#19596) this is a workaround, but there should be a better way - fn walk_(&self, it: &mut G) -> bool - where G: FnMut(&Pat) -> bool - { + fn walk_short_(&self, it: &mut impl FnMut(&Pat) -> bool) -> bool { if !it(self) { return false; } + use PatKind::*; match &self.node { - PatKind::Binding(.., Some(p)) => p.walk_(it), - PatKind::Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_(it)), - PatKind::TupleStruct(_, s, _) | PatKind::Tuple(s, _) | PatKind::Or(s) => { - s.iter().all(|p| p.walk_(it)) - } - PatKind::Box(s) | PatKind::Ref(s, _) => s.walk_(it), - PatKind::Slice(before, slice, after) => { + Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => true, + Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_short_(it), + Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)), + TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)), + Slice(before, slice, after) => { before.iter() .chain(slice.iter()) .chain(after.iter()) - .all(|p| p.walk_(it)) + .all(|p| p.walk_short_(it)) } - PatKind::Wild | - PatKind::Lit(_) | - PatKind::Range(..) | - PatKind::Binding(..) | - PatKind::Path(_) => { - true + } + } + + /// Walk the pattern in left-to-right order, + /// short circuiting (with `.all(..)`) if `false` is returned. + /// + /// Note that when visiting e.g. `Tuple(ps)`, + /// if visiting `ps[0]` returns `false`, + /// then `ps[1]` will not be visited. + pub fn walk_short(&self, mut it: impl FnMut(&Pat) -> bool) -> bool { + self.walk_short_(&mut it) + } + + // FIXME(#19596) this is a workaround, but there should be a better way + fn walk_(&self, it: &mut impl FnMut(&Pat) -> bool) { + if !it(self) { + return; + } + + use PatKind::*; + match &self.node { + Wild | Lit(_) | Range(..) | Binding(.., None) | Path(_) => {}, + Box(s) | Ref(s, _) | Binding(.., Some(s)) => s.walk_(it), + Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)), + TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)), + Slice(before, slice, after) => { + before.iter() + .chain(slice.iter()) + .chain(after.iter()) + .for_each(|p| p.walk_(it)) } } } - pub fn walk(&self, mut it: F) -> bool - where F: FnMut(&Pat) -> bool - { + /// Walk the pattern in left-to-right order. + /// + /// If `it(pat)` returns `false`, the children are not visited. + pub fn walk(&self, mut it: impl FnMut(&Pat) -> bool) { self.walk_(&mut it) } } diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs index ea35418bc1ba7..118e168f87767 100644 --- a/src/librustc/hir/pat_util.rs +++ b/src/librustc/hir/pat_util.rs @@ -66,9 +66,7 @@ impl hir::Pat { /// Call `f` on every "binding" in a pattern, e.g., on `a` in /// `match foo() { Some(a) => (), None => () }` - pub fn each_binding(&self, mut f: F) - where F: FnMut(hir::BindingAnnotation, HirId, Span, ast::Ident), - { + pub fn each_binding(&self, mut f: impl FnMut(hir::BindingAnnotation, HirId, Span, ast::Ident)) { self.walk(|p| { if let PatKind::Binding(binding_mode, _, ident, _) = p.node { f(binding_mode, p.hir_id, p.span, ident); @@ -81,59 +79,53 @@ impl hir::Pat { /// `match foo() { Some(a) => (), None => () }`. /// /// When encountering an or-pattern `p_0 | ... | p_n` only `p_0` will be visited. - pub fn each_binding_or_first(&self, c: &mut F) - where F: FnMut(hir::BindingAnnotation, HirId, Span, ast::Ident), - { - match &self.node { - PatKind::Binding(bm, _, ident, sub) => { - c(*bm, self.hir_id, self.span, *ident); - sub.iter().for_each(|p| p.each_binding_or_first(c)); - } - PatKind::Or(ps) => ps[0].each_binding_or_first(c), - PatKind::Struct(_, fs, _) => fs.iter().for_each(|f| f.pat.each_binding_or_first(c)), - PatKind::TupleStruct(_, ps, _) | PatKind::Tuple(ps, _) => { - ps.iter().for_each(|p| p.each_binding_or_first(c)); - } - PatKind::Box(p) | PatKind::Ref(p, _) => p.each_binding_or_first(c), - PatKind::Slice(before, slice, after) => { - before.iter() - .chain(slice.iter()) - .chain(after.iter()) - .for_each(|p| p.each_binding_or_first(c)); + pub fn each_binding_or_first( + &self, + f: &mut impl FnMut(hir::BindingAnnotation, HirId, Span, ast::Ident), + ) { + self.walk(|p| match &p.node { + PatKind::Or(ps) => { + ps[0].each_binding_or_first(f); + false + }, + PatKind::Binding(bm, _, ident, _) => { + f(*bm, p.hir_id, p.span, *ident); + true } - PatKind::Wild | PatKind::Lit(_) | PatKind::Range(..) | PatKind::Path(_) => {} - } + _ => true, + }) } /// Checks if the pattern contains any patterns that bind something to /// an ident, e.g., `foo`, or `Foo(foo)` or `foo @ Bar(..)`. pub fn contains_bindings(&self) -> bool { - let mut contains_bindings = false; - self.walk(|p| { - if let PatKind::Binding(..) = p.node { - contains_bindings = true; - false // there's at least one binding, can short circuit now. - } else { - true - } - }); - contains_bindings + self.satisfies(|p| match p.node { + PatKind::Binding(..) => true, + _ => false, + }) } /// Checks if the pattern contains any patterns that bind something to /// an ident or wildcard, e.g., `foo`, or `Foo(_)`, `foo @ Bar(..)`, pub fn contains_bindings_or_wild(&self) -> bool { - let mut contains_bindings = false; - self.walk(|p| { - match p.node { - PatKind::Binding(..) | PatKind::Wild => { - contains_bindings = true; - false // there's at least one binding/wildcard, can short circuit now. - } - _ => true + self.satisfies(|p| match p.node { + PatKind::Binding(..) | PatKind::Wild => true, + _ => false, + }) + } + + /// Checks if the pattern satisfies the given predicate on some sub-pattern. + fn satisfies(&self, pred: impl Fn(&Self) -> bool) -> bool { + let mut satisfies = false; + self.walk_short(|p| { + if pred(p) { + satisfies = true; + false // Found one, can short circuit now. + } else { + true } }); - contains_bindings + satisfies } pub fn simple_ident(&self) -> Option { @@ -147,20 +139,20 @@ impl hir::Pat { /// Returns variants that are necessary to exist for the pattern to match. pub fn necessary_variants(&self) -> Vec { let mut variants = vec![]; - self.walk(|p| { - match p.node { - PatKind::Path(hir::QPath::Resolved(_, ref path)) | - PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) | - PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => { - match path.res { - Res::Def(DefKind::Variant, id) => variants.push(id), - Res::Def(DefKind::Ctor(CtorOf::Variant, ..), id) => variants.push(id), - _ => () - } + self.walk(|p| match &p.node { + PatKind::Or(_) => false, + PatKind::Path(hir::QPath::Resolved(_, path)) | + PatKind::TupleStruct(hir::QPath::Resolved(_, path), ..) | + PatKind::Struct(hir::QPath::Resolved(_, path), ..) => { + if let Res::Def(DefKind::Variant, id) + | Res::Def(DefKind::Ctor(CtorOf::Variant, ..), id) + = path.res + { + variants.push(id); } - _ => () + true } - true + _ => true, }); variants.sort(); variants.dedup(); @@ -176,14 +168,12 @@ impl hir::Pat { let mut result = None; self.each_binding(|annotation, _, _, _| { match annotation { - hir::BindingAnnotation::Ref => { - match result { - None | Some(hir::MutImmutable) => result = Some(hir::MutImmutable), - _ => (), - } + hir::BindingAnnotation::Ref => match result { + None | Some(hir::MutImmutable) => result = Some(hir::MutImmutable), + _ => {} } hir::BindingAnnotation::RefMut => result = Some(hir::MutMutable), - _ => (), + _ => {} } }); result diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 1818dede3e229..2746794e2a2c1 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -259,20 +259,13 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { } fn visit_arm(&mut self, arm: &'tcx hir::Arm) { - let pats = arm.top_pats_hack(); - if let [pat] = pats { - let variants = pat.necessary_variants(); - - // Inside the body, ignore constructions of variants - // necessary for the pattern to match. Those construction sites - // can't be reached unless the variant is constructed elsewhere. - let len = self.ignore_variant_stack.len(); - self.ignore_variant_stack.extend_from_slice(&variants); - intravisit::walk_arm(self, arm); - self.ignore_variant_stack.truncate(len); - } else { - intravisit::walk_arm(self, arm); - } + // Inside the body, ignore constructions of variants + // necessary for the pattern to match. Those construction sites + // can't be reached unless the variant is constructed elsewhere. + let len = self.ignore_variant_stack.len(); + self.ignore_variant_stack.extend(arm.pat.necessary_variants()); + intravisit::walk_arm(self, arm); + self.ignore_variant_stack.truncate(len); } fn visit_pat(&mut self, pat: &'tcx hir::Pat) { From 983e035b11d90787fe27c5c31203b4e03ea0266a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 13 Sep 2019 15:14:28 +0200 Subject: [PATCH 068/413] add long error explanation for E0524 --- src/librustc_mir/error_codes.rs | 64 ++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/error_codes.rs b/src/librustc_mir/error_codes.rs index ba299e9463b8d..196bcf147f8f8 100644 --- a/src/librustc_mir/error_codes.rs +++ b/src/librustc_mir/error_codes.rs @@ -1993,6 +1993,69 @@ fn get_owned_iterator() -> IntoIter { ``` "##, +E0524: r##" +A variable which requires unique access is being used in more than one closure +at the same time. + +Erroneous code example: + +```compile_fail,E0524 +fn set(x: &mut isize) { + *x += 4; +} + +fn dragoooon(x: &mut isize) { + let mut c1 = || set(x); + let mut c2 = || set(x); // error! + + c2(); + c1(); +} +``` + +To solve this issue, multiple solutions are available. First, is it required +for this variable to be used in more than one closure at a time? If it is the +case, use reference counted types such as `Rc` (or `Arc` if it runs +concurrently): + +``` +use std::rc::Rc; +use std::cell::RefCell; + +fn set(x: &mut isize) { + *x += 4; +} + +fn dragoooon(x: &mut isize) { + let x = Rc::new(RefCell::new(x)); + let y = Rc::clone(&x); + let mut c1 = || { let mut x2 = x.borrow_mut(); set(&mut x2); }; + let mut c2 = || { let mut x2 = y.borrow_mut(); set(&mut x2); }; // ok! + + c2(); + c1(); +} +``` + +If not, just run closures one at a time: + +``` +fn set(x: &mut isize) { + *x += 4; +} + +fn dragoooon(x: &mut isize) { + { // This block isn't necessary since non-lexical lifetimes, it's just to + // make it more clear. + let mut c1 = || set(&mut *x); + c1(); + } // `c1` has been dropped here so we're free to use `x` again! + let mut c2 = || set(&mut *x); + c2(); +} +``` +"##, + E0595: r##" #### Note: this error code is no longer emitted by the compiler. @@ -2393,7 +2456,6 @@ There are some known bugs that trigger this message. // E0385, // {} in an aliasable location E0493, // destructors cannot be evaluated at compile-time E0521, // borrowed data escapes outside of closure - E0524, // two closures require unique access to `..` at the same time E0526, // shuffle indices are not constant E0594, // cannot assign to {} // E0598, // lifetime of {} is too short to guarantee its contents can be... From d2b873b06706e97dc54317b8c0ad8f9efa1c3b70 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 13 Sep 2019 15:14:53 +0200 Subject: [PATCH 069/413] update ui tests --- src/test/ui/borrowck/borrowck-closures-mut-of-imm.rs | 4 ---- src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr | 9 +++++---- src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr | 1 + src/test/ui/borrowck/borrowck-closures-unique.stderr | 3 ++- src/test/ui/nll/closures-in-loops.stderr | 2 +- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/test/ui/borrowck/borrowck-closures-mut-of-imm.rs b/src/test/ui/borrowck/borrowck-closures-mut-of-imm.rs index 24e06e3c4e666..d7e187a2b3958 100644 --- a/src/test/ui/borrowck/borrowck-closures-mut-of-imm.rs +++ b/src/test/ui/borrowck/borrowck-closures-mut-of-imm.rs @@ -1,10 +1,6 @@ // Tests that two closures cannot simultaneously have mutable // and immutable access to the variable. Issue #6801. -fn get(x: &isize) -> isize { - *x -} - fn set(x: &mut isize) { *x = 4; } diff --git a/src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr b/src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr index 3be7d725eda3a..784b903a5896a 100644 --- a/src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr +++ b/src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr @@ -1,17 +1,17 @@ error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference - --> $DIR/borrowck-closures-mut-of-imm.rs:13:25 + --> $DIR/borrowck-closures-mut-of-imm.rs:9:25 | LL | let mut c1 = || set(&mut *x); | ^^^^^^^ cannot borrow as mutable error[E0596]: cannot borrow `*x` as mutable, as it is behind a `&` reference - --> $DIR/borrowck-closures-mut-of-imm.rs:15:25 + --> $DIR/borrowck-closures-mut-of-imm.rs:11:25 | LL | let mut c2 = || set(&mut *x); | ^^^^^^^ cannot borrow as mutable error[E0524]: two closures require unique access to `x` at the same time - --> $DIR/borrowck-closures-mut-of-imm.rs:15:18 + --> $DIR/borrowck-closures-mut-of-imm.rs:11:18 | LL | let mut c1 = || set(&mut *x); | -- - first borrow occurs due to use of `x` in closure @@ -28,4 +28,5 @@ LL | c2(); c1(); error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0596`. +Some errors have detailed explanations: E0524, E0596. +For more information about an error, try `rustc --explain E0524`. diff --git a/src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr b/src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr index a174388712158..471173e595f47 100644 --- a/src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr +++ b/src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr @@ -15,3 +15,4 @@ LL | c2(); c1(); error: aborting due to previous error +For more information about this error, try `rustc --explain E0524`. diff --git a/src/test/ui/borrowck/borrowck-closures-unique.stderr b/src/test/ui/borrowck/borrowck-closures-unique.stderr index 9b53af4c01f59..2ed08b83c58b9 100644 --- a/src/test/ui/borrowck/borrowck-closures-unique.stderr +++ b/src/test/ui/borrowck/borrowck-closures-unique.stderr @@ -50,4 +50,5 @@ LL | let c1 = |y: &'static mut isize| x = y; error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0500`. +Some errors have detailed explanations: E0500, E0524. +For more information about an error, try `rustc --explain E0500`. diff --git a/src/test/ui/nll/closures-in-loops.stderr b/src/test/ui/nll/closures-in-loops.stderr index 7603f9650b54a..0b15d9bcfe68c 100644 --- a/src/test/ui/nll/closures-in-loops.stderr +++ b/src/test/ui/nll/closures-in-loops.stderr @@ -27,5 +27,5 @@ LL | v.push(|| *x = String::new()); error: aborting due to 3 previous errors -Some errors have detailed explanations: E0382, E0499. +Some errors have detailed explanations: E0382, E0499, E0524. For more information about an error, try `rustc --explain E0382`. From c16a547012b93272a77d58ff7de894848c4c935a Mon Sep 17 00:00:00 2001 From: Jakob Schikowski Date: Sat, 21 Sep 2019 19:03:14 +0200 Subject: [PATCH 070/413] libtest: Add --report-time flag to print test execution time --- src/libtest/formatters/json.rs | 32 ++++++++-- src/libtest/formatters/mod.rs | 1 + src/libtest/formatters/pretty.rs | 29 +++++---- src/libtest/formatters/terse.rs | 1 + src/libtest/lib.rs | 101 +++++++++++++++++++++++-------- src/libtest/tests.rs | 46 ++++++++++++-- 6 files changed, 162 insertions(+), 48 deletions(-) diff --git a/src/libtest/formatters/json.rs b/src/libtest/formatters/json.rs index e0bea4ce54530..d9e4abf61c3dc 100644 --- a/src/libtest/formatters/json.rs +++ b/src/libtest/formatters/json.rs @@ -27,6 +27,7 @@ impl JsonFormatter { ty: &str, name: &str, evt: &str, + exec_time: Option<&TestExecTime>, stdout: Option>, extra: Option<&str>, ) -> io::Result<()> { @@ -34,6 +35,12 @@ impl JsonFormatter { r#"{{ "type": "{}", "name": "{}", "event": "{}""#, ty, name, evt ))?; + if let Some(exec_time) = exec_time { + self.write_message(&*format!( + r#", "exec_time": "{}""#, + exec_time + ))?; + } if let Some(stdout) = stdout { self.write_message(&*format!( r#", "stdout": "{}""#, @@ -69,6 +76,7 @@ impl OutputFormatter for JsonFormatter { &mut self, desc: &TestDesc, result: &TestResult, + exec_time: Option<&TestExecTime>, stdout: &[u8], state: &ConsoleTestState, ) -> io::Result<()> { @@ -78,24 +86,36 @@ impl OutputFormatter for JsonFormatter { None }; match *result { - TrOk => self.write_event("test", desc.name.as_slice(), "ok", stdout, None), + TrOk => { + self.write_event("test", desc.name.as_slice(), "ok", exec_time, stdout, None) + } - TrFailed => self.write_event("test", desc.name.as_slice(), "failed", stdout, None), + TrFailed => { + self.write_event("test", desc.name.as_slice(), "failed", exec_time, stdout, None) + } TrFailedMsg(ref m) => self.write_event( "test", desc.name.as_slice(), "failed", + exec_time, stdout, Some(&*format!(r#""message": "{}""#, EscapedString(m))), ), - TrIgnored => self.write_event("test", desc.name.as_slice(), "ignored", stdout, None), - - TrAllowedFail => { - self.write_event("test", desc.name.as_slice(), "allowed_failure", stdout, None) + TrIgnored => { + self.write_event("test", desc.name.as_slice(), "ignored", exec_time, stdout, None) } + TrAllowedFail => self.write_event( + "test", + desc.name.as_slice(), + "allowed_failure", + exec_time, + stdout, + None, + ), + TrBench(ref bs) => { let median = bs.ns_iter_summ.median as usize; let deviation = (bs.ns_iter_summ.max - bs.ns_iter_summ.min) as usize; diff --git a/src/libtest/formatters/mod.rs b/src/libtest/formatters/mod.rs index cc30b06e5ec38..e97cda76d2318 100644 --- a/src/libtest/formatters/mod.rs +++ b/src/libtest/formatters/mod.rs @@ -16,6 +16,7 @@ pub(crate) trait OutputFormatter { &mut self, desc: &TestDesc, result: &TestResult, + exec_time: Option<&TestExecTime>, stdout: &[u8], state: &ConsoleTestState, ) -> io::Result<()>; diff --git a/src/libtest/formatters/pretty.rs b/src/libtest/formatters/pretty.rs index 88331406a64d0..184726c67d3fb 100644 --- a/src/libtest/formatters/pretty.rs +++ b/src/libtest/formatters/pretty.rs @@ -30,20 +30,20 @@ impl PrettyFormatter { &self.out } - pub fn write_ok(&mut self) -> io::Result<()> { - self.write_short_result("ok", term::color::GREEN) + pub fn write_ok(&mut self, exec_time: Option<&TestExecTime>) -> io::Result<()> { + self.write_short_result("ok", term::color::GREEN, exec_time) } - pub fn write_failed(&mut self) -> io::Result<()> { - self.write_short_result("FAILED", term::color::RED) + pub fn write_failed(&mut self, exec_time: Option<&TestExecTime>) -> io::Result<()> { + self.write_short_result("FAILED", term::color::RED, exec_time) } - pub fn write_ignored(&mut self) -> io::Result<()> { - self.write_short_result("ignored", term::color::YELLOW) + pub fn write_ignored(&mut self, exec_time: Option<&TestExecTime>) -> io::Result<()> { + self.write_short_result("ignored", term::color::YELLOW, exec_time) } - pub fn write_allowed_fail(&mut self) -> io::Result<()> { - self.write_short_result("FAILED (allowed)", term::color::YELLOW) + pub fn write_allowed_fail(&mut self, exec_time: Option<&TestExecTime>) -> io::Result<()> { + self.write_short_result("FAILED (allowed)", term::color::YELLOW, exec_time) } pub fn write_bench(&mut self) -> io::Result<()> { @@ -54,8 +54,12 @@ impl PrettyFormatter { &mut self, result: &str, color: term::color::Color, + exec_time: Option<&TestExecTime>, ) -> io::Result<()> { self.write_pretty(result, color)?; + if let Some(exec_time) = exec_time { + self.write_plain(format!(" {}", exec_time))?; + } self.write_plain("\n") } @@ -166,6 +170,7 @@ impl OutputFormatter for PrettyFormatter { &mut self, desc: &TestDesc, result: &TestResult, + exec_time: Option<&TestExecTime>, _: &[u8], _: &ConsoleTestState, ) -> io::Result<()> { @@ -174,10 +179,10 @@ impl OutputFormatter for PrettyFormatter { } match *result { - TrOk => self.write_ok(), - TrFailed | TrFailedMsg(_) => self.write_failed(), - TrIgnored => self.write_ignored(), - TrAllowedFail => self.write_allowed_fail(), + TrOk => self.write_ok(exec_time), + TrFailed | TrFailedMsg(_) => self.write_failed(exec_time), + TrIgnored => self.write_ignored(exec_time), + TrAllowedFail => self.write_allowed_fail(exec_time), TrBench(ref bs) => { self.write_bench()?; self.write_plain(&format!(": {}\n", fmt_bench_samples(bs))) diff --git a/src/libtest/formatters/terse.rs b/src/libtest/formatters/terse.rs index d10b0c5807d57..1812c20904c87 100644 --- a/src/libtest/formatters/terse.rs +++ b/src/libtest/formatters/terse.rs @@ -174,6 +174,7 @@ impl OutputFormatter for TerseFormatter { &mut self, desc: &TestDesc, result: &TestResult, + _: Option<&TestExecTime>, _: &[u8], _: &ConsoleTestState, ) -> io::Result<()> { diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 09d5fcc89520e..17baf98875c76 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -378,6 +378,7 @@ pub struct TestOpts { pub format: OutputFormat, pub test_threads: Option, pub skip: Vec, + pub report_time: bool, pub options: Options, } @@ -460,6 +461,11 @@ fn optgroups() -> getopts::Options { "Enable nightly-only flags: unstable-options = Allow use of experimental features", "unstable-options", + ) + .optflag( + "", + "report-time", + "Show execution time of each test. Not available for --format=terse" ); return opts; } @@ -573,6 +579,7 @@ pub fn parse_opts(args: &[String]) -> Option { let quiet = matches.opt_present("quiet"); let exact = matches.opt_present("exact"); let list = matches.opt_present("list"); + let report_time = matches.opt_present("report-time"); let logfile = matches.opt_str("logfile"); let logfile = logfile.map(|s| PathBuf::from(&s)); @@ -653,6 +660,7 @@ pub fn parse_opts(args: &[String]) -> Option { format, test_threads, skip: matches.opt_strs("skip"), + report_time, options: Options::new().display_output(matches.opt_present("show-output")), }; @@ -677,6 +685,16 @@ pub enum TestResult { unsafe impl Send for TestResult {} +/// The meassured execution time of a unit test. +#[derive(Clone, PartialEq)] +pub struct TestExecTime(Duration); + +impl fmt::Display for TestExecTime { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:.3}s", self.0.as_secs_f64()) + } +} + enum OutputLocation { Pretty(Box), Raw(T), @@ -736,17 +754,30 @@ impl ConsoleTestState { }) } - pub fn write_log>(&mut self, msg: S) -> io::Result<()> { - let msg = msg.as_ref(); + pub fn write_log( + &mut self, + msg: F, + ) -> io::Result<()> + where + S: AsRef, + F: FnOnce() -> S, + { match self.log_out { None => Ok(()), - Some(ref mut o) => o.write_all(msg.as_bytes()), + Some(ref mut o) => { + let msg = msg(); + let msg = msg.as_ref(); + o.write_all(msg.as_bytes()) + }, } } - pub fn write_log_result(&mut self, test: &TestDesc, result: &TestResult) -> io::Result<()> { - self.write_log(format!( - "{} {}\n", + pub fn write_log_result(&mut self,test: &TestDesc, + result: &TestResult, + exec_time: Option<&TestExecTime>, + ) -> io::Result<()> { + self.write_log(|| format!( + "{} {}", match *result { TrOk => "ok".to_owned(), TrFailed => "failed".to_owned(), @@ -755,8 +786,12 @@ impl ConsoleTestState { TrAllowedFail => "failed (allowed)".to_owned(), TrBench(ref bs) => fmt_bench_samples(bs), }, - test.name - )) + test.name, + ))?; + if let Some(exec_time) = exec_time { + self.write_log(|| format!(" {}", exec_time))?; + } + self.write_log(|| "\n") } fn current_test_count(&self) -> usize { @@ -843,7 +878,7 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec) -> io::Res }; writeln!(output, "{}: {}", name, fntype)?; - st.write_log(format!("{} {}\n", fntype, name))?; + st.write_log(|| format!("{} {}\n", fntype, name))?; } fn plural(count: u32, s: &str) -> String { @@ -884,9 +919,9 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Resu TeFilteredOut(filtered_out) => Ok(st.filtered_out = filtered_out), TeWait(ref test) => out.write_test_start(test), TeTimeout(ref test) => out.write_timeout(test), - TeResult(test, result, stdout) => { - st.write_log_result(&test, &result)?; - out.write_result(&test, &result, &*stdout, &st)?; + TeResult(test, result, exec_time, stdout) => { + st.write_log_result(&test, &result, exec_time.as_ref())?; + out.write_result(&test, &result, exec_time.as_ref(), &*stdout, &st)?; match result { TrOk => { st.passed += 1; @@ -1004,12 +1039,12 @@ fn stdout_isatty() -> bool { pub enum TestEvent { TeFiltered(Vec), TeWait(TestDesc), - TeResult(TestDesc, TestResult, Vec), + TeResult(TestDesc, TestResult, Option, Vec), TeTimeout(TestDesc), TeFilteredOut(usize), } -pub type MonitorMsg = (TestDesc, TestResult, Vec); +pub type MonitorMsg = (TestDesc, TestResult, Option, Vec); struct Sink(Arc>>); impl Write for Sink { @@ -1105,8 +1140,8 @@ where let test = remaining.pop().unwrap(); callback(TeWait(test.desc.clone()))?; run_test(opts, !opts.run_tests, test, tx.clone(), Concurrent::No); - let (test, result, stdout) = rx.recv().unwrap(); - callback(TeResult(test, result, stdout))?; + let (test, result, exec_time, stdout) = rx.recv().unwrap(); + callback(TeResult(test, result, exec_time, stdout))?; } } else { while pending > 0 || !remaining.is_empty() { @@ -1135,10 +1170,10 @@ where } } - let (desc, result, stdout) = res.unwrap(); + let (desc, result, exec_time, stdout) = res.unwrap(); running_tests.remove(&desc); - callback(TeResult(desc, result, stdout))?; + callback(TeResult(desc, result, exec_time, stdout))?; pending -= 1; } } @@ -1148,8 +1183,8 @@ where for b in filtered_benchs { callback(TeWait(b.desc.clone()))?; run_test(opts, false, b, tx.clone(), Concurrent::No); - let (test, result, stdout) = rx.recv().unwrap(); - callback(TeResult(test, result, stdout))?; + let (test, result, exec_time, stdout) = rx.recv().unwrap(); + callback(TeResult(test, result, exec_time, stdout))?; } } Ok(()) @@ -1384,7 +1419,7 @@ pub fn run_test( && desc.should_panic != ShouldPanic::No; if force_ignore || desc.ignore || ignore_because_panic_abort { - monitor_ch.send((desc, TrIgnored, Vec::new())).unwrap(); + monitor_ch.send((desc, TrIgnored, None, Vec::new())).unwrap(); return; } @@ -1392,6 +1427,7 @@ pub fn run_test( desc: TestDesc, monitor_ch: Sender, nocapture: bool, + report_time: bool, testfn: Box, concurrency: Concurrent, ) { @@ -1410,7 +1446,16 @@ pub fn run_test( None }; + let start = if report_time { + Some(Instant::now()) + } else { + None + }; let result = catch_unwind(AssertUnwindSafe(testfn)); + let exec_time = start.map(|start| { + let duration = start.elapsed(); + TestExecTime(duration) + }); if let Some((printio, panicio)) = oldio { io::set_print(printio); @@ -1420,7 +1465,7 @@ pub fn run_test( let test_result = calc_result(&desc, result); let stdout = data.lock().unwrap().to_vec(); monitor_ch - .send((desc.clone(), test_result, stdout)) + .send((desc.clone(), test_result, exec_time, stdout)) .unwrap(); }; @@ -1449,12 +1494,20 @@ pub fn run_test( } DynTestFn(f) => { let cb = move || __rust_begin_short_backtrace(f); - run_test_inner(desc, monitor_ch, opts.nocapture, Box::new(cb), concurrency) + run_test_inner( + desc, + monitor_ch, + opts.nocapture, + opts.report_time, + Box::new(cb), + concurrency, + ) } StaticTestFn(f) => run_test_inner( desc, monitor_ch, opts.nocapture, + opts.report_time, Box::new(move || __rust_begin_short_backtrace(f)), concurrency, ), @@ -1702,7 +1755,7 @@ pub mod bench { }; let stdout = data.lock().unwrap().to_vec(); - monitor_ch.send((desc, test_result, stdout)).unwrap(); + monitor_ch.send((desc, test_result, None, stdout)).unwrap(); } pub fn run_once(f: F) diff --git a/src/libtest/tests.rs b/src/libtest/tests.rs index afc4217ec1ba2..13ac8eb91f411 100644 --- a/src/libtest/tests.rs +++ b/src/libtest/tests.rs @@ -23,6 +23,7 @@ impl TestOpts { format: OutputFormat::Pretty, test_threads: None, skip: vec![], + report_time: false, options: Options::new(), } } @@ -67,7 +68,7 @@ pub fn do_not_run_ignored_tests() { }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); - let (_, res, _) = rx.recv().unwrap(); + let (_, res, _, _) = rx.recv().unwrap(); assert!(res != TrOk); } @@ -85,7 +86,7 @@ pub fn ignored_tests_result_in_ignored() { }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); - let (_, res, _) = rx.recv().unwrap(); + let (_, res, _, _) = rx.recv().unwrap(); assert!(res == TrIgnored); } @@ -105,7 +106,7 @@ fn test_should_panic() { }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); - let (_, res, _) = rx.recv().unwrap(); + let (_, res, _, _) = rx.recv().unwrap(); assert!(res == TrOk); } @@ -125,7 +126,7 @@ fn test_should_panic_good_message() { }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); - let (_, res, _) = rx.recv().unwrap(); + let (_, res, _, _) = rx.recv().unwrap(); assert!(res == TrOk); } @@ -147,7 +148,7 @@ fn test_should_panic_bad_message() { }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); - let (_, res, _) = rx.recv().unwrap(); + let (_, res, _, _) = rx.recv().unwrap(); assert!(res == TrFailedMsg(format!("{} '{}'", failed_msg, expected))); } @@ -165,10 +166,43 @@ fn test_should_panic_but_succeeds() { }; let (tx, rx) = channel(); run_test(&TestOpts::new(), false, desc, tx, Concurrent::No); - let (_, res, _) = rx.recv().unwrap(); + let (_, res, _, _) = rx.recv().unwrap(); assert!(res == TrFailed); } +fn report_time_test_template(report_time: bool) -> Option { + fn f() {} + let desc = TestDescAndFn { + desc: TestDesc { + name: StaticTestName("whatever"), + ignore: false, + should_panic: ShouldPanic::No, + allow_fail: false, + }, + testfn: DynTestFn(Box::new(f)), + }; + let test_opts = TestOpts { + report_time, + ..TestOpts::new() + }; + let (tx, rx) = channel(); + run_test(&test_opts, false, desc, tx, Concurrent::No); + let (_, _, exec_time, _) = rx.recv().unwrap(); + exec_time +} + +#[test] +fn test_should_not_report_time() { + let exec_time = report_time_test_template(false); + assert!(exec_time.is_none()); +} + +#[test] +fn test_should_report_time() { + let exec_time = report_time_test_template(true); + assert!(exec_time.is_some()); +} + #[test] fn parse_ignored_flag() { let args = vec![ From 92e91f7541af929010638355dc16daf27fd28b65 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 18 Sep 2019 21:36:30 -0700 Subject: [PATCH 071/413] Remove manual unrolling from slice::Iter(Mut)::try_fold While this definitely helps sometimes (particularly for trivial closures), it's also a pessimization sometimes, so it's better to leave this to (hypothetical) future LLVM improvements instead of forcing this on everyone. I think it's better for the advice to be that sometimes you need to unroll manually than you sometimes need to not-unroll manually (like #64545). --- src/libcore/slice/mod.rs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 931768564ca3c..59f95cff5aee1 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -3184,18 +3184,14 @@ macro_rules! iterator { fn try_fold(&mut self, init: B, mut f: F) -> R where Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try { - // manual unrolling is needed when there are conditional exits from the loop + // This method historically was unrolled, for as of 2019-09 LLVM + // is not capable of unrolling or vectorizing multiple-exit loops. + // However, doing it always proved to often be a pessimization, + // especially when called with large closures, so it was removed. + let mut accum = init; - unsafe { - while len!(self) >= 4 { - accum = f(accum, next_unchecked!(self))?; - accum = f(accum, next_unchecked!(self))?; - accum = f(accum, next_unchecked!(self))?; - accum = f(accum, next_unchecked!(self))?; - } - while !is_empty!(self) { - accum = f(accum, next_unchecked!(self))?; - } + while let Some(x) = self.next() { + accum = f(accum, x)?; } Try::from_ok(accum) } @@ -3204,8 +3200,6 @@ macro_rules! iterator { fn fold(mut self, init: Acc, mut f: Fold) -> Acc where Fold: FnMut(Acc, Self::Item) -> Acc, { - // Let LLVM unroll this, rather than using the default - // impl that would force the manual unrolling above let mut accum = init; while let Some(x) = self.next() { accum = f(accum, x); From 3ee292021d00857586af0d2ef1fa6c31f74181ce Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Sun, 22 Sep 2019 12:59:10 +0200 Subject: [PATCH 072/413] Fix some unused variable warnings --- src/test/ui/coherence/auxiliary/coherence_lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/coherence/auxiliary/coherence_lib.rs b/src/test/ui/coherence/auxiliary/coherence_lib.rs index 9a5ec82430639..c22819831ab24 100644 --- a/src/test/ui/coherence/auxiliary/coherence_lib.rs +++ b/src/test/ui/coherence/auxiliary/coherence_lib.rs @@ -5,11 +5,11 @@ pub trait Remote { } pub trait Remote1 { - fn foo(&self, t: T) { } + fn foo(&self, _t: T) { } } pub trait Remote2 { - fn foo(&self, t: T, u: U) { } + fn foo(&self, _t: T, _u: U) { } } pub struct Pair(T,U); From 645cdca9ba2fd3e47dedeecbb580d490fa9ef85b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Sep 2019 17:42:17 +0300 Subject: [PATCH 073/413] reduce visibility of a bunch of stuff in ext::tt --- src/librustc_resolve/macros.rs | 4 +- src/libsyntax/ext/tt/macro_check.rs | 2 +- src/libsyntax/ext/tt/macro_parser.rs | 16 ++++---- src/libsyntax/ext/tt/macro_rules.rs | 14 ++++--- src/libsyntax/ext/tt/quoted.rs | 57 +++++++++++----------------- src/libsyntax/lib.rs | 13 ++++--- src/libsyntax/tokenstream.rs | 2 +- 7 files changed, 50 insertions(+), 58 deletions(-) diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 3900a3dbb3872..73ad0670659b5 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -18,7 +18,7 @@ use syntax::ext::base::{self, InvocationRes, Indeterminate, SpecialDerives}; use syntax::ext::base::{MacroKind, SyntaxExtension}; use syntax::ext::expand::{AstFragment, AstFragmentKind, Invocation, InvocationKind}; use syntax::ext::hygiene::{self, ExpnId, ExpnData, ExpnKind}; -use syntax::ext::tt::macro_rules; +use syntax::ext::compile_declarative_macro; use syntax::feature_gate::{emit_feature_err, is_builtin_attr_name}; use syntax::feature_gate::GateIssue; use syntax::symbol::{Symbol, kw, sym}; @@ -843,7 +843,7 @@ impl<'a> Resolver<'a> { /// Compile the macro into a `SyntaxExtension` and possibly replace it with a pre-defined /// extension partially or entirely for built-in macros and legacy plugin macros. crate fn compile_macro(&mut self, item: &ast::Item, edition: Edition) -> SyntaxExtension { - let mut result = macro_rules::compile( + let mut result = compile_declarative_macro( &self.session.parse_sess, self.session.features_untracked(), item, edition ); diff --git a/src/libsyntax/ext/tt/macro_check.rs b/src/libsyntax/ext/tt/macro_check.rs index 5af97199902e6..a1734689595f0 100644 --- a/src/libsyntax/ext/tt/macro_check.rs +++ b/src/libsyntax/ext/tt/macro_check.rs @@ -196,7 +196,7 @@ struct MacroState<'a> { /// - `node_id` is used to emit lints /// - `span` is used when no spans are available /// - `lhses` and `rhses` should have the same length and represent the macro definition -pub fn check_meta_variables( +crate fn check_meta_variables( sess: &ParseSess, node_id: NodeId, span: Span, diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index dbf14daa30e75..a34a0344f2740 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -70,8 +70,8 @@ //! eof: [a $( a )* a b ·] //! ``` -pub use NamedMatch::*; -pub use ParseResult::*; +crate use NamedMatch::*; +crate use ParseResult::*; use TokenTreeOrTokenTreeSlice::*; use crate::ast::{Ident, Name}; @@ -267,7 +267,7 @@ impl<'root, 'tt> DerefMut for MatcherPosHandle<'root, 'tt> { } /// Represents the possible results of an attempted parse. -pub enum ParseResult { +crate enum ParseResult { /// Parsed successfully. Success(T), /// Arm failed to match. If the second parameter is `token::Eof`, it indicates an unexpected @@ -279,10 +279,10 @@ pub enum ParseResult { /// A `ParseResult` where the `Success` variant contains a mapping of `Ident`s to `NamedMatch`es. /// This represents the mapping of metavars to the token trees they bind to. -pub type NamedParseResult = ParseResult>; +crate type NamedParseResult = ParseResult>; /// Count how many metavars are named in the given matcher `ms`. -pub fn count_names(ms: &[TokenTree]) -> usize { +crate fn count_names(ms: &[TokenTree]) -> usize { ms.iter().fold(0, |count, elt| { count + match *elt { TokenTree::Sequence(_, ref seq) => seq.num_captures, @@ -352,7 +352,7 @@ fn initial_matcher_pos<'root, 'tt>(ms: &'tt [TokenTree], open: Span) -> MatcherP /// only on the nesting depth of `ast::TTSeq`s in the originating /// token tree it was derived from. #[derive(Debug, Clone)] -pub enum NamedMatch { +crate enum NamedMatch { MatchedSeq(Lrc, DelimSpan), MatchedNonterminal(Lrc), } @@ -415,7 +415,7 @@ fn nameize>( /// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For /// other tokens, this is "unexpected token...". -pub fn parse_failure_msg(tok: &Token) -> String { +crate fn parse_failure_msg(tok: &Token) -> String { match tok.kind { token::Eof => "unexpected end of macro invocation".to_string(), _ => format!( @@ -648,7 +648,7 @@ fn inner_parse_loop<'root, 'tt>( /// - `directory`: Information about the file locations (needed for the black-box parser) /// - `recurse_into_modules`: Whether or not to recurse into modules (needed for the black-box /// parser) -pub fn parse( +crate fn parse( sess: &ParseSess, tts: TokenStream, ms: &[TokenTree], diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index b27e9c543377a..90dfa6e7ac8a4 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -35,7 +35,7 @@ const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \ `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \ `literal`, `path`, `meta`, `tt`, `item` and `vis`"; -pub struct ParserAnyMacro<'a> { +crate struct ParserAnyMacro<'a> { parser: Parser<'a>, /// Span of the expansion site of the macro this parser is for @@ -45,7 +45,11 @@ pub struct ParserAnyMacro<'a> { arm_span: Span, } -pub fn annotate_err_with_kind(err: &mut DiagnosticBuilder<'_>, kind: AstFragmentKind, span: Span) { +crate fn annotate_err_with_kind( + err: &mut DiagnosticBuilder<'_>, + kind: AstFragmentKind, + span: Span, +) { match kind { AstFragmentKind::Ty => { err.span_label(span, "this macro call doesn't expand to a type"); @@ -58,7 +62,7 @@ pub fn annotate_err_with_kind(err: &mut DiagnosticBuilder<'_>, kind: AstFragment } impl<'a> ParserAnyMacro<'a> { - pub fn make(mut self: Box>, kind: AstFragmentKind) -> AstFragment { + crate fn make(mut self: Box>, kind: AstFragmentKind) -> AstFragment { let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self; let fragment = panictry!(parser.parse_ast_fragment(kind, true).map_err(|mut e| { if parser.token == token::Eof && e.message().ends_with(", found ``") { @@ -284,8 +288,8 @@ fn generic_extension<'cx>( // // Holy self-referential! -/// Converts a `macro_rules!` invocation into a syntax extension. -pub fn compile( +/// Converts a macro item into a syntax extension. +pub fn compile_declarative_macro( sess: &ParseSess, features: &Features, def: &ast::Item, diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index cad94a0e4c120..d161e6638bf75 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -16,14 +16,14 @@ use std::iter::Peekable; /// Contains the sub-token-trees of a "delimited" token tree, such as the contents of `(`. Note /// that the delimiter itself might be `NoDelim`. #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] -pub struct Delimited { - pub delim: token::DelimToken, - pub tts: Vec, +crate struct Delimited { + crate delim: token::DelimToken, + crate tts: Vec, } impl Delimited { /// Returns a `self::TokenTree` with a `Span` corresponding to the opening delimiter. - pub fn open_tt(&self, span: Span) -> TokenTree { + crate fn open_tt(&self, span: Span) -> TokenTree { let open_span = if span.is_dummy() { span } else { @@ -33,7 +33,7 @@ impl Delimited { } /// Returns a `self::TokenTree` with a `Span` corresponding to the closing delimiter. - pub fn close_tt(&self, span: Span) -> TokenTree { + crate fn close_tt(&self, span: Span) -> TokenTree { let close_span = if span.is_dummy() { span } else { @@ -44,25 +44,25 @@ impl Delimited { } #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] -pub struct SequenceRepetition { +crate struct SequenceRepetition { /// The sequence of token trees - pub tts: Vec, + crate tts: Vec, /// The optional separator - pub separator: Option, + crate separator: Option, /// Whether the sequence can be repeated zero (*), or one or more times (+) - pub kleene: KleeneToken, + crate kleene: KleeneToken, /// The number of `Match`s that appear in the sequence (and subsequences) - pub num_captures: usize, + crate num_captures: usize, } #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] -pub struct KleeneToken { - pub span: Span, - pub op: KleeneOp, +crate struct KleeneToken { + crate span: Span, + crate op: KleeneOp, } impl KleeneToken { - pub fn new(op: KleeneOp, span: Span) -> KleeneToken { + crate fn new(op: KleeneOp, span: Span) -> KleeneToken { KleeneToken { span, op } } } @@ -70,7 +70,7 @@ impl KleeneToken { /// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star) /// for token sequences. #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -pub enum KleeneOp { +crate enum KleeneOp { /// Kleene star (`*`) for zero or more repetitions ZeroOrMore, /// Kleene plus (`+`) for one or more repetitions @@ -82,7 +82,7 @@ pub enum KleeneOp { /// Similar to `tokenstream::TokenTree`, except that `$i`, `$i:ident`, and `$(...)` /// are "first-class" token trees. Useful for parsing macros. #[derive(Debug, Clone, PartialEq, RustcEncodable, RustcDecodable)] -pub enum TokenTree { +crate enum TokenTree { Token(Token), Delimited(DelimSpan, Lrc), /// A kleene-style repetition sequence @@ -99,7 +99,7 @@ pub enum TokenTree { impl TokenTree { /// Return the number of tokens in the tree. - pub fn len(&self) -> usize { + crate fn len(&self) -> usize { match *self { TokenTree::Delimited(_, ref delimed) => match delimed.delim { token::NoDelim => delimed.tts.len(), @@ -110,21 +110,8 @@ impl TokenTree { } } - /// Returns `true` if the given token tree contains no other tokens. This is vacuously true for - /// single tokens or metavar/decls, but may be false for delimited trees or sequences. - pub fn is_empty(&self) -> bool { - match *self { - TokenTree::Delimited(_, ref delimed) => match delimed.delim { - token::NoDelim => delimed.tts.is_empty(), - _ => false, - }, - TokenTree::Sequence(_, ref seq) => seq.tts.is_empty(), - _ => true, - } - } - /// Returns `true` if the given token tree is delimited. - pub fn is_delimited(&self) -> bool { + crate fn is_delimited(&self) -> bool { match *self { TokenTree::Delimited(..) => true, _ => false, @@ -132,7 +119,7 @@ impl TokenTree { } /// Returns `true` if the given token tree is a token of the given kind. - pub fn is_token(&self, expected_kind: &TokenKind) -> bool { + crate fn is_token(&self, expected_kind: &TokenKind) -> bool { match self { TokenTree::Token(Token { kind: actual_kind, .. }) => actual_kind == expected_kind, _ => false, @@ -140,7 +127,7 @@ impl TokenTree { } /// Gets the `index`-th sub-token-tree. This only makes sense for delimited trees and sequences. - pub fn get_tt(&self, index: usize) -> TokenTree { + crate fn get_tt(&self, index: usize) -> TokenTree { match (self, index) { (&TokenTree::Delimited(_, ref delimed), _) if delimed.delim == token::NoDelim => { delimed.tts[index].clone() @@ -160,7 +147,7 @@ impl TokenTree { } /// Retrieves the `TokenTree`'s span. - pub fn span(&self) -> Span { + crate fn span(&self) -> Span { match *self { TokenTree::Token(Token { span, .. }) | TokenTree::MetaVar(span, _) @@ -195,7 +182,7 @@ impl TokenTree { /// # Returns /// /// A collection of `self::TokenTree`. There may also be some errors emitted to `sess`. -pub fn parse( +crate fn parse( input: tokenstream::TokenStream, expect_matchers: bool, sess: &ParseSess, diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index aaf6f3e537eb6..c06f43021021a 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -162,18 +162,19 @@ pub mod ext { mod proc_macro_server; pub use syntax_pos::hygiene; + pub use tt::macro_rules::compile_declarative_macro; pub mod allocator; pub mod base; pub mod build; pub mod expand; pub mod proc_macro; - pub mod tt { - pub mod transcribe; - pub mod macro_check; - pub mod macro_parser; - pub mod macro_rules; - pub mod quoted; + crate mod tt { + crate mod transcribe; + crate mod macro_check; + crate mod macro_parser; + crate mod macro_rules; + crate mod quoted; } } diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index d702038f54ec3..15fc4b02041b7 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -64,7 +64,7 @@ where impl TokenTree { /// Use this token tree as a matcher to parse given tts. - pub fn parse(cx: &base::ExtCtxt<'_>, mtch: &[quoted::TokenTree], tts: TokenStream) + crate fn parse(cx: &base::ExtCtxt<'_>, mtch: &[quoted::TokenTree], tts: TokenStream) -> macro_parser::NamedParseResult { // `None` is because we're not interpolating let directory = Directory { From 827a5b2ea8dc66bfdf817f52011f470f00bc6fee Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Sep 2019 18:19:51 +0300 Subject: [PATCH 074/413] rename libsyntax::ext::tt to mbe mbe stands for macro-by-example --- src/libsyntax/ext/{tt => mbe}/macro_check.rs | 0 src/libsyntax/ext/{tt => mbe}/macro_parser.rs | 0 src/libsyntax/ext/{tt => mbe}/macro_rules.rs | 0 src/libsyntax/ext/{tt => mbe}/quoted.rs | 0 src/libsyntax/ext/{tt => mbe}/transcribe.rs | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename src/libsyntax/ext/{tt => mbe}/macro_check.rs (100%) rename src/libsyntax/ext/{tt => mbe}/macro_parser.rs (100%) rename src/libsyntax/ext/{tt => mbe}/macro_rules.rs (100%) rename src/libsyntax/ext/{tt => mbe}/quoted.rs (100%) rename src/libsyntax/ext/{tt => mbe}/transcribe.rs (100%) diff --git a/src/libsyntax/ext/tt/macro_check.rs b/src/libsyntax/ext/mbe/macro_check.rs similarity index 100% rename from src/libsyntax/ext/tt/macro_check.rs rename to src/libsyntax/ext/mbe/macro_check.rs diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/mbe/macro_parser.rs similarity index 100% rename from src/libsyntax/ext/tt/macro_parser.rs rename to src/libsyntax/ext/mbe/macro_parser.rs diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/mbe/macro_rules.rs similarity index 100% rename from src/libsyntax/ext/tt/macro_rules.rs rename to src/libsyntax/ext/mbe/macro_rules.rs diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/mbe/quoted.rs similarity index 100% rename from src/libsyntax/ext/tt/quoted.rs rename to src/libsyntax/ext/mbe/quoted.rs diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/mbe/transcribe.rs similarity index 100% rename from src/libsyntax/ext/tt/transcribe.rs rename to src/libsyntax/ext/mbe/transcribe.rs From 49f849cdb7910162f15ac6ac26a98ba22009dc9a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Sep 2019 18:25:29 +0300 Subject: [PATCH 075/413] rename tt -> mbe, part 2 --- src/libsyntax/ext/expand.rs | 6 +++--- src/libsyntax/ext/mbe/macro_check.rs | 2 +- src/libsyntax/ext/mbe/macro_parser.rs | 2 +- src/libsyntax/ext/mbe/macro_rules.rs | 12 ++++++------ src/libsyntax/ext/mbe/quoted.rs | 2 +- src/libsyntax/ext/mbe/transcribe.rs | 4 ++-- src/libsyntax/lib.rs | 4 ++-- src/libsyntax/tokenstream.rs | 2 +- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index b80c530731dfc..2cd802f22d306 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -6,7 +6,7 @@ use crate::config::StripUnconfigured; use crate::ext::base::*; use crate::ext::proc_macro::{collect_derives, MarkAttrs}; use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnData, ExpnKind}; -use crate::ext::tt::macro_rules::annotate_err_with_kind; +use crate::ext::mbe::macro_rules::annotate_err_with_kind; use crate::ext::placeholders::{placeholder, PlaceholderExpander}; use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err}; use crate::mut_visit::*; @@ -115,8 +115,8 @@ macro_rules! ast_fragments { } } - impl<'a> MacResult for crate::ext::tt::macro_rules::ParserAnyMacro<'a> { - $(fn $make_ast(self: Box>) + impl<'a> MacResult for crate::ext::mbe::macro_rules::ParserAnyMacro<'a> { + $(fn $make_ast(self: Box>) -> Option<$AstTy> { Some(self.make(AstFragmentKind::$Kind).$make_ast()) })* diff --git a/src/libsyntax/ext/mbe/macro_check.rs b/src/libsyntax/ext/mbe/macro_check.rs index a1734689595f0..aa88d71666eb5 100644 --- a/src/libsyntax/ext/mbe/macro_check.rs +++ b/src/libsyntax/ext/mbe/macro_check.rs @@ -106,7 +106,7 @@ //! bound. use crate::ast::NodeId; use crate::early_buffered_lints::BufferedEarlyLintId; -use crate::ext::tt::quoted::{KleeneToken, TokenTree}; +use crate::ext::mbe::quoted::{KleeneToken, TokenTree}; use crate::parse::token::TokenKind; use crate::parse::token::{DelimToken, Token}; use crate::parse::ParseSess; diff --git a/src/libsyntax/ext/mbe/macro_parser.rs b/src/libsyntax/ext/mbe/macro_parser.rs index a34a0344f2740..88145cd121f14 100644 --- a/src/libsyntax/ext/mbe/macro_parser.rs +++ b/src/libsyntax/ext/mbe/macro_parser.rs @@ -75,7 +75,7 @@ crate use ParseResult::*; use TokenTreeOrTokenTreeSlice::*; use crate::ast::{Ident, Name}; -use crate::ext::tt::quoted::{self, TokenTree}; +use crate::ext::mbe::quoted::{self, TokenTree}; use crate::parse::{Directory, ParseSess}; use crate::parse::parser::{Parser, PathStyle}; use crate::parse::token::{self, DocComment, Nonterminal, Token}; diff --git a/src/libsyntax/ext/mbe/macro_rules.rs b/src/libsyntax/ext/mbe/macro_rules.rs index 90dfa6e7ac8a4..939f5b8f51d57 100644 --- a/src/libsyntax/ext/mbe/macro_rules.rs +++ b/src/libsyntax/ext/mbe/macro_rules.rs @@ -4,12 +4,12 @@ use crate::edition::Edition; use crate::ext::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander}; use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind}; use crate::ext::expand::{AstFragment, AstFragmentKind}; -use crate::ext::tt::macro_check; -use crate::ext::tt::macro_parser::{parse, parse_failure_msg}; -use crate::ext::tt::macro_parser::{Error, Failure, Success}; -use crate::ext::tt::macro_parser::{MatchedNonterminal, MatchedSeq}; -use crate::ext::tt::quoted; -use crate::ext::tt::transcribe::transcribe; +use crate::ext::mbe::macro_check; +use crate::ext::mbe::macro_parser::{parse, parse_failure_msg}; +use crate::ext::mbe::macro_parser::{Error, Failure, Success}; +use crate::ext::mbe::macro_parser::{MatchedNonterminal, MatchedSeq}; +use crate::ext::mbe::quoted; +use crate::ext::mbe::transcribe::transcribe; use crate::feature_gate::Features; use crate::parse::parser::Parser; use crate::parse::token::TokenKind::*; diff --git a/src/libsyntax/ext/mbe/quoted.rs b/src/libsyntax/ext/mbe/quoted.rs index d161e6638bf75..8ef2834523112 100644 --- a/src/libsyntax/ext/mbe/quoted.rs +++ b/src/libsyntax/ext/mbe/quoted.rs @@ -1,6 +1,6 @@ use crate::ast; use crate::ast::NodeId; -use crate::ext::tt::macro_parser; +use crate::ext::mbe::macro_parser; use crate::feature_gate::Features; use crate::parse::token::{self, Token, TokenKind}; use crate::parse::ParseSess; diff --git a/src/libsyntax/ext/mbe/transcribe.rs b/src/libsyntax/ext/mbe/transcribe.rs index f9c07e3a2e4ff..94ac1f60c6407 100644 --- a/src/libsyntax/ext/mbe/transcribe.rs +++ b/src/libsyntax/ext/mbe/transcribe.rs @@ -1,7 +1,7 @@ use crate::ast::{Ident, Mac}; use crate::ext::base::ExtCtxt; -use crate::ext::tt::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch}; -use crate::ext::tt::quoted; +use crate::ext::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch}; +use crate::ext::mbe::quoted; use crate::mut_visit::{self, MutVisitor}; use crate::parse::token::{self, NtTT, Token}; use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint}; diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index c06f43021021a..045a36931883c 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -162,14 +162,14 @@ pub mod ext { mod proc_macro_server; pub use syntax_pos::hygiene; - pub use tt::macro_rules::compile_declarative_macro; + pub use mbe::macro_rules::compile_declarative_macro; pub mod allocator; pub mod base; pub mod build; pub mod expand; pub mod proc_macro; - crate mod tt { + crate mod mbe { crate mod transcribe; crate mod macro_check; crate mod macro_parser; diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 15fc4b02041b7..d46e38f53d51b 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -14,7 +14,7 @@ //! ownership of the original. use crate::ext::base; -use crate::ext::tt::{macro_parser, quoted}; +use crate::ext::mbe::{macro_parser, quoted}; use crate::parse::Directory; use crate::parse::token::{self, DelimToken, Token, TokenKind}; use crate::print::pprust; From e30c5166db72f9f1ceccc355df25b49df826df02 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Sep 2019 18:28:32 +0300 Subject: [PATCH 076/413] move mbe module to a separate file --- src/libsyntax/ext/mbe.rs | 5 +++++ src/libsyntax/lib.rs | 8 +------- 2 files changed, 6 insertions(+), 7 deletions(-) create mode 100644 src/libsyntax/ext/mbe.rs diff --git a/src/libsyntax/ext/mbe.rs b/src/libsyntax/ext/mbe.rs new file mode 100644 index 0000000000000..b77b59fea7039 --- /dev/null +++ b/src/libsyntax/ext/mbe.rs @@ -0,0 +1,5 @@ +crate mod transcribe; +crate mod macro_check; +crate mod macro_parser; +crate mod macro_rules; +crate mod quoted; diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 045a36931883c..402d563010fdc 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -169,13 +169,7 @@ pub mod ext { pub mod expand; pub mod proc_macro; - crate mod mbe { - crate mod transcribe; - crate mod macro_check; - crate mod macro_parser; - crate mod macro_rules; - crate mod quoted; - } + crate mod mbe; } pub mod early_buffered_lints; From 636b3543c27e1eba301605afd2143fc96fd14431 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Sep 2019 20:36:35 +0300 Subject: [PATCH 077/413] docstring for mbe module --- src/libsyntax/ext/mbe.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libsyntax/ext/mbe.rs b/src/libsyntax/ext/mbe.rs index b77b59fea7039..78d96f471fa7f 100644 --- a/src/libsyntax/ext/mbe.rs +++ b/src/libsyntax/ext/mbe.rs @@ -1,3 +1,8 @@ +//! This module implements declarative macros: old `macro_rules` and the newer +//! `macro`. Declarative macros are also known as "macro by example", and that's +//! why we call this module `mbe`. For external documentation, prefer the +//! official terminology: "declarative macros". + crate mod transcribe; crate mod macro_check; crate mod macro_parser; From 9fd75f52877a3e23a7b9a6a9675f37a42340a428 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Sep 2019 19:17:30 +0300 Subject: [PATCH 078/413] pull mbe token tree definition up --- src/libsyntax/ext/mbe.rs | 156 ++++++++++++++++++++++++++ src/libsyntax/ext/mbe/macro_check.rs | 2 +- src/libsyntax/ext/mbe/macro_parser.rs | 10 +- src/libsyntax/ext/mbe/macro_rules.rs | 116 +++++++++---------- src/libsyntax/ext/mbe/quoted.rs | 155 +------------------------ src/libsyntax/ext/mbe/transcribe.rs | 34 +++--- src/libsyntax/tokenstream.rs | 4 +- 7 files changed, 243 insertions(+), 234 deletions(-) diff --git a/src/libsyntax/ext/mbe.rs b/src/libsyntax/ext/mbe.rs index 78d96f471fa7f..c18b8918ff1e3 100644 --- a/src/libsyntax/ext/mbe.rs +++ b/src/libsyntax/ext/mbe.rs @@ -8,3 +8,159 @@ crate mod macro_check; crate mod macro_parser; crate mod macro_rules; crate mod quoted; + +use crate::ast; +use crate::parse::token::{self, Token, TokenKind}; +use crate::tokenstream::{DelimSpan}; + +use syntax_pos::{BytePos, Span}; + +use rustc_data_structures::sync::Lrc; + +/// Contains the sub-token-trees of a "delimited" token tree, such as the contents of `(`. Note +/// that the delimiter itself might be `NoDelim`. +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] +crate struct Delimited { + crate delim: token::DelimToken, + crate tts: Vec, +} + +impl Delimited { + /// Returns a `self::TokenTree` with a `Span` corresponding to the opening delimiter. + crate fn open_tt(&self, span: Span) -> TokenTree { + let open_span = if span.is_dummy() { + span + } else { + span.with_hi(span.lo() + BytePos(self.delim.len() as u32)) + }; + TokenTree::token(token::OpenDelim(self.delim), open_span) + } + + /// Returns a `self::TokenTree` with a `Span` corresponding to the closing delimiter. + crate fn close_tt(&self, span: Span) -> TokenTree { + let close_span = if span.is_dummy() { + span + } else { + span.with_lo(span.hi() - BytePos(self.delim.len() as u32)) + }; + TokenTree::token(token::CloseDelim(self.delim), close_span) + } +} + +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] +crate struct SequenceRepetition { + /// The sequence of token trees + crate tts: Vec, + /// The optional separator + crate separator: Option, + /// Whether the sequence can be repeated zero (*), or one or more times (+) + crate kleene: KleeneToken, + /// The number of `Match`s that appear in the sequence (and subsequences) + crate num_captures: usize, +} + +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] +crate struct KleeneToken { + crate span: Span, + crate op: KleeneOp, +} + +impl KleeneToken { + crate fn new(op: KleeneOp, span: Span) -> KleeneToken { + KleeneToken { span, op } + } +} + +/// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star) +/// for token sequences. +#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] +crate enum KleeneOp { + /// Kleene star (`*`) for zero or more repetitions + ZeroOrMore, + /// Kleene plus (`+`) for one or more repetitions + OneOrMore, + /// Kleene optional (`?`) for zero or one reptitions + ZeroOrOne, +} + +/// Similar to `tokenstream::TokenTree`, except that `$i`, `$i:ident`, and `$(...)` +/// are "first-class" token trees. Useful for parsing macros. +#[derive(Debug, Clone, PartialEq, RustcEncodable, RustcDecodable)] +crate enum TokenTree { + Token(Token), + Delimited(DelimSpan, Lrc), + /// A kleene-style repetition sequence + Sequence(DelimSpan, Lrc), + /// e.g., `$var` + MetaVar(Span, ast::Ident), + /// e.g., `$var:expr`. This is only used in the left hand side of MBE macros. + MetaVarDecl( + Span, + ast::Ident, /* name to bind */ + ast::Ident, /* kind of nonterminal */ + ), +} + +impl TokenTree { + /// Return the number of tokens in the tree. + crate fn len(&self) -> usize { + match *self { + TokenTree::Delimited(_, ref delimed) => match delimed.delim { + token::NoDelim => delimed.tts.len(), + _ => delimed.tts.len() + 2, + }, + TokenTree::Sequence(_, ref seq) => seq.tts.len(), + _ => 0, + } + } + + /// Returns `true` if the given token tree is delimited. + crate fn is_delimited(&self) -> bool { + match *self { + TokenTree::Delimited(..) => true, + _ => false, + } + } + + /// Returns `true` if the given token tree is a token of the given kind. + crate fn is_token(&self, expected_kind: &TokenKind) -> bool { + match self { + TokenTree::Token(Token { kind: actual_kind, .. }) => actual_kind == expected_kind, + _ => false, + } + } + + /// Gets the `index`-th sub-token-tree. This only makes sense for delimited trees and sequences. + crate fn get_tt(&self, index: usize) -> TokenTree { + match (self, index) { + (&TokenTree::Delimited(_, ref delimed), _) if delimed.delim == token::NoDelim => { + delimed.tts[index].clone() + } + (&TokenTree::Delimited(span, ref delimed), _) => { + if index == 0 { + return delimed.open_tt(span.open); + } + if index == delimed.tts.len() + 1 { + return delimed.close_tt(span.close); + } + delimed.tts[index - 1].clone() + } + (&TokenTree::Sequence(_, ref seq), _) => seq.tts[index].clone(), + _ => panic!("Cannot expand a token tree"), + } + } + + /// Retrieves the `TokenTree`'s span. + crate fn span(&self) -> Span { + match *self { + TokenTree::Token(Token { span, .. }) + | TokenTree::MetaVar(span, _) + | TokenTree::MetaVarDecl(span, _, _) => span, + TokenTree::Delimited(span, _) | TokenTree::Sequence(span, _) => span.entire(), + } + } + + crate fn token(kind: TokenKind, span: Span) -> TokenTree { + TokenTree::Token(Token::new(kind, span)) + } +} diff --git a/src/libsyntax/ext/mbe/macro_check.rs b/src/libsyntax/ext/mbe/macro_check.rs index aa88d71666eb5..a3750e5c46945 100644 --- a/src/libsyntax/ext/mbe/macro_check.rs +++ b/src/libsyntax/ext/mbe/macro_check.rs @@ -106,7 +106,7 @@ //! bound. use crate::ast::NodeId; use crate::early_buffered_lints::BufferedEarlyLintId; -use crate::ext::mbe::quoted::{KleeneToken, TokenTree}; +use crate::ext::mbe::{KleeneToken, TokenTree}; use crate::parse::token::TokenKind; use crate::parse::token::{DelimToken, Token}; use crate::parse::ParseSess; diff --git a/src/libsyntax/ext/mbe/macro_parser.rs b/src/libsyntax/ext/mbe/macro_parser.rs index 88145cd121f14..35fc6cf21b80e 100644 --- a/src/libsyntax/ext/mbe/macro_parser.rs +++ b/src/libsyntax/ext/mbe/macro_parser.rs @@ -75,7 +75,7 @@ crate use ParseResult::*; use TokenTreeOrTokenTreeSlice::*; use crate::ast::{Ident, Name}; -use crate::ext::mbe::quoted::{self, TokenTree}; +use crate::ext::mbe::{self, TokenTree}; use crate::parse::{Directory, ParseSess}; use crate::parse::parser::{Parser, PathStyle}; use crate::parse::token::{self, DocComment, Nonterminal, Token}; @@ -195,7 +195,7 @@ struct MatcherPos<'root, 'tt> { // `None`. /// The KleeneOp of this sequence if we are in a repetition. - seq_op: Option, + seq_op: Option, /// The separator if we are in a repetition. sep: Option, @@ -532,7 +532,7 @@ fn inner_parse_loop<'root, 'tt>( } // We don't need a separator. Move the "dot" back to the beginning of the matcher // and try to match again UNLESS we are only allowed to have _one_ repetition. - else if item.seq_op != Some(quoted::KleeneOp::ZeroOrOne) { + else if item.seq_op != Some(mbe::KleeneOp::ZeroOrOne) { item.match_cur = item.match_lo; item.idx = 0; cur_items.push(item); @@ -555,8 +555,8 @@ fn inner_parse_loop<'root, 'tt>( // implicitly disallowing OneOrMore from having 0 matches here. Thus, that will // result in a "no rules expected token" error by virtue of this matcher not // working. - if seq.kleene.op == quoted::KleeneOp::ZeroOrMore - || seq.kleene.op == quoted::KleeneOp::ZeroOrOne + if seq.kleene.op == mbe::KleeneOp::ZeroOrMore + || seq.kleene.op == mbe::KleeneOp::ZeroOrOne { let mut new_item = item.clone(); new_item.match_cur += seq.num_captures; diff --git a/src/libsyntax/ext/mbe/macro_rules.rs b/src/libsyntax/ext/mbe/macro_rules.rs index 939f5b8f51d57..2ec171a7fb591 100644 --- a/src/libsyntax/ext/mbe/macro_rules.rs +++ b/src/libsyntax/ext/mbe/macro_rules.rs @@ -4,11 +4,11 @@ use crate::edition::Edition; use crate::ext::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander}; use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind}; use crate::ext::expand::{AstFragment, AstFragmentKind}; +use crate::ext::mbe; use crate::ext::mbe::macro_check; use crate::ext::mbe::macro_parser::{parse, parse_failure_msg}; use crate::ext::mbe::macro_parser::{Error, Failure, Success}; use crate::ext::mbe::macro_parser::{MatchedNonterminal, MatchedSeq}; -use crate::ext::mbe::quoted; use crate::ext::mbe::transcribe::transcribe; use crate::feature_gate::Features; use crate::parse::parser::Parser; @@ -135,8 +135,8 @@ struct MacroRulesMacroExpander { name: ast::Ident, span: Span, transparency: Transparency, - lhses: Vec, - rhses: Vec, + lhses: Vec, + rhses: Vec, valid: bool, } @@ -169,8 +169,8 @@ fn generic_extension<'cx>( name: ast::Ident, transparency: Transparency, arg: TokenStream, - lhses: &[quoted::TokenTree], - rhses: &[quoted::TokenTree], + lhses: &[mbe::TokenTree], + rhses: &[mbe::TokenTree], ) -> Box { if cx.trace_macros() { trace_macros_note(cx, sp, format!("expanding `{}! {{ {} }}`", name, arg)); @@ -182,7 +182,7 @@ fn generic_extension<'cx>( for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers let lhs_tt = match *lhs { - quoted::TokenTree::Delimited(_, ref delim) => &delim.tts[..], + mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..], _ => cx.span_bug(sp, "malformed macro lhs"), }; @@ -190,7 +190,7 @@ fn generic_extension<'cx>( Success(named_matches) => { let rhs = match rhses[i] { // ignore delimiters - quoted::TokenTree::Delimited(_, ref delimed) => delimed.tts.clone(), + mbe::TokenTree::Delimited(_, ref delimed) => delimed.tts.clone(), _ => cx.span_bug(sp, "malformed macro rhs"), }; let arm_span = rhses[i].span(); @@ -258,7 +258,7 @@ fn generic_extension<'cx>( for lhs in lhses { // try each arm's matchers let lhs_tt = match *lhs { - quoted::TokenTree::Delimited(_, ref delim) => &delim.tts[..], + mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..], _ => continue, }; match TokenTree::parse(cx, lhs_tt, arg.clone()) { @@ -312,32 +312,32 @@ pub fn compile_declarative_macro( // ...quasiquoting this would be nice. // These spans won't matter, anyways let argument_gram = vec![ - quoted::TokenTree::Sequence( + mbe::TokenTree::Sequence( DelimSpan::dummy(), - Lrc::new(quoted::SequenceRepetition { + Lrc::new(mbe::SequenceRepetition { tts: vec![ - quoted::TokenTree::MetaVarDecl(def.span, lhs_nm, tt_spec), - quoted::TokenTree::token(token::FatArrow, def.span), - quoted::TokenTree::MetaVarDecl(def.span, rhs_nm, tt_spec), + mbe::TokenTree::MetaVarDecl(def.span, lhs_nm, tt_spec), + mbe::TokenTree::token(token::FatArrow, def.span), + mbe::TokenTree::MetaVarDecl(def.span, rhs_nm, tt_spec), ], separator: Some(Token::new( if body.legacy { token::Semi } else { token::Comma }, def.span, )), - kleene: quoted::KleeneToken::new(quoted::KleeneOp::OneOrMore, def.span), + kleene: mbe::KleeneToken::new(mbe::KleeneOp::OneOrMore, def.span), num_captures: 2, }), ), // to phase into semicolon-termination instead of semicolon-separation - quoted::TokenTree::Sequence( + mbe::TokenTree::Sequence( DelimSpan::dummy(), - Lrc::new(quoted::SequenceRepetition { - tts: vec![quoted::TokenTree::token( + Lrc::new(mbe::SequenceRepetition { + tts: vec![mbe::TokenTree::token( if body.legacy { token::Semi } else { token::Comma }, def.span, )], separator: None, - kleene: quoted::KleeneToken::new(quoted::KleeneOp::ZeroOrMore, def.span), + kleene: mbe::KleeneToken::new(mbe::KleeneOp::ZeroOrMore, def.span), num_captures: 0, }), ), @@ -367,7 +367,7 @@ pub fn compile_declarative_macro( .map(|m| { if let MatchedNonterminal(ref nt) = *m { if let NtTT(ref tt) = **nt { - let tt = quoted::parse( + let tt = mbe::quoted::parse( tt.clone().into(), true, sess, @@ -384,7 +384,7 @@ pub fn compile_declarative_macro( } sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs") }) - .collect::>(), + .collect::>(), _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs"), }; @@ -394,7 +394,7 @@ pub fn compile_declarative_macro( .map(|m| { if let MatchedNonterminal(ref nt) = *m { if let NtTT(ref tt) = **nt { - return quoted::parse( + return mbe::quoted::parse( tt.clone().into(), false, sess, @@ -409,7 +409,7 @@ pub fn compile_declarative_macro( } sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs") }) - .collect::>(), + .collect::>(), _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs"), }; @@ -454,11 +454,11 @@ fn check_lhs_nt_follows( sess: &ParseSess, features: &Features, attrs: &[ast::Attribute], - lhs: "ed::TokenTree, + lhs: &mbe::TokenTree, ) -> bool { // lhs is going to be like TokenTree::Delimited(...), where the // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens. - if let quoted::TokenTree::Delimited(_, ref tts) = *lhs { + if let mbe::TokenTree::Delimited(_, ref tts) = *lhs { check_matcher(sess, features, attrs, &tts.tts) } else { let msg = "invalid macro matcher; matchers must be contained in balanced delimiters"; @@ -471,8 +471,8 @@ fn check_lhs_nt_follows( /// Checks that the lhs contains no repetition which could match an empty token /// tree, because then the matcher would hang indefinitely. -fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[quoted::TokenTree]) -> bool { - use quoted::TokenTree; +fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool { + use mbe::TokenTree; for tt in tts { match *tt { TokenTree::Token(..) | TokenTree::MetaVar(..) | TokenTree::MetaVarDecl(..) => (), @@ -486,8 +486,8 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[quoted::TokenTree]) -> bool { && seq.tts.iter().all(|seq_tt| match *seq_tt { TokenTree::MetaVarDecl(_, _, id) => id.name == sym::vis, TokenTree::Sequence(_, ref sub_seq) => { - sub_seq.kleene.op == quoted::KleeneOp::ZeroOrMore - || sub_seq.kleene.op == quoted::KleeneOp::ZeroOrOne + sub_seq.kleene.op == mbe::KleeneOp::ZeroOrMore + || sub_seq.kleene.op == mbe::KleeneOp::ZeroOrOne } _ => false, }) @@ -506,9 +506,9 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[quoted::TokenTree]) -> bool { true } -fn check_rhs(sess: &ParseSess, rhs: "ed::TokenTree) -> bool { +fn check_rhs(sess: &ParseSess, rhs: &mbe::TokenTree) -> bool { match *rhs { - quoted::TokenTree::Delimited(..) => return true, + mbe::TokenTree::Delimited(..) => return true, _ => sess.span_diagnostic.span_err(rhs.span(), "macro rhs must be delimited"), } false @@ -518,7 +518,7 @@ fn check_matcher( sess: &ParseSess, features: &Features, attrs: &[ast::Attribute], - matcher: &[quoted::TokenTree], + matcher: &[mbe::TokenTree], ) -> bool { let first_sets = FirstSets::new(matcher); let empty_suffix = TokenSet::empty(); @@ -550,8 +550,8 @@ struct FirstSets { } impl FirstSets { - fn new(tts: &[quoted::TokenTree]) -> FirstSets { - use quoted::TokenTree; + fn new(tts: &[mbe::TokenTree]) -> FirstSets { + use mbe::TokenTree; let mut sets = FirstSets { first: FxHashMap::default() }; build_recur(&mut sets, tts); @@ -598,8 +598,8 @@ impl FirstSets { // Reverse scan: Sequence comes before `first`. if subfirst.maybe_empty - || seq_rep.kleene.op == quoted::KleeneOp::ZeroOrMore - || seq_rep.kleene.op == quoted::KleeneOp::ZeroOrOne + || seq_rep.kleene.op == mbe::KleeneOp::ZeroOrMore + || seq_rep.kleene.op == mbe::KleeneOp::ZeroOrOne { // If sequence is potentially empty, then // union them (preserving first emptiness). @@ -619,8 +619,8 @@ impl FirstSets { // walks forward over `tts` until all potential FIRST tokens are // identified. - fn first(&self, tts: &[quoted::TokenTree]) -> TokenSet { - use quoted::TokenTree; + fn first(&self, tts: &[mbe::TokenTree]) -> TokenSet { + use mbe::TokenTree; let mut first = TokenSet::empty(); for tt in tts.iter() { @@ -656,8 +656,8 @@ impl FirstSets { assert!(first.maybe_empty); first.add_all(subfirst); if subfirst.maybe_empty - || seq_rep.kleene.op == quoted::KleeneOp::ZeroOrMore - || seq_rep.kleene.op == quoted::KleeneOp::ZeroOrOne + || seq_rep.kleene.op == mbe::KleeneOp::ZeroOrMore + || seq_rep.kleene.op == mbe::KleeneOp::ZeroOrOne { // Continue scanning for more first // tokens, but also make sure we @@ -678,7 +678,7 @@ impl FirstSets { } } -// A set of `quoted::TokenTree`s, which may include `TokenTree::Match`s +// A set of `mbe::TokenTree`s, which may include `TokenTree::Match`s // (for macro-by-example syntactic variables). It also carries the // `maybe_empty` flag; that is true if and only if the matcher can // match an empty token sequence. @@ -690,7 +690,7 @@ impl FirstSets { // (Notably, we must allow for *-op to occur zero times.) #[derive(Clone, Debug)] struct TokenSet { - tokens: Vec, + tokens: Vec, maybe_empty: bool, } @@ -702,13 +702,13 @@ impl TokenSet { // Returns the set `{ tok }` for the single-token (and thus // non-empty) sequence [tok]. - fn singleton(tok: quoted::TokenTree) -> Self { + fn singleton(tok: mbe::TokenTree) -> Self { TokenSet { tokens: vec![tok], maybe_empty: false } } // Changes self to be the set `{ tok }`. // Since `tok` is always present, marks self as non-empty. - fn replace_with(&mut self, tok: quoted::TokenTree) { + fn replace_with(&mut self, tok: mbe::TokenTree) { self.tokens.clear(); self.tokens.push(tok); self.maybe_empty = false; @@ -723,7 +723,7 @@ impl TokenSet { } // Adds `tok` to the set for `self`, marking sequence as non-empy. - fn add_one(&mut self, tok: quoted::TokenTree) { + fn add_one(&mut self, tok: mbe::TokenTree) { if !self.tokens.contains(&tok) { self.tokens.push(tok); } @@ -731,7 +731,7 @@ impl TokenSet { } // Adds `tok` to the set for `self`. (Leaves `maybe_empty` flag alone.) - fn add_one_maybe(&mut self, tok: quoted::TokenTree) { + fn add_one_maybe(&mut self, tok: mbe::TokenTree) { if !self.tokens.contains(&tok) { self.tokens.push(tok); } @@ -772,10 +772,10 @@ fn check_matcher_core( features: &Features, attrs: &[ast::Attribute], first_sets: &FirstSets, - matcher: &[quoted::TokenTree], + matcher: &[mbe::TokenTree], follow: &TokenSet, ) -> TokenSet { - use quoted::TokenTree; + use mbe::TokenTree; let mut last = TokenSet::empty(); @@ -950,8 +950,8 @@ fn check_matcher_core( last } -fn token_can_be_followed_by_any(tok: "ed::TokenTree) -> bool { - if let quoted::TokenTree::MetaVarDecl(_, _, frag_spec) = *tok { +fn token_can_be_followed_by_any(tok: &mbe::TokenTree) -> bool { + if let mbe::TokenTree::MetaVarDecl(_, _, frag_spec) = *tok { frag_can_be_followed_by_any(frag_spec.name) } else { // (Non NT's can always be followed by anthing in matchers.) @@ -997,8 +997,8 @@ enum IsInFollow { /// break macros that were relying on that binary operator as a /// separator. // when changing this do not forget to update doc/book/macros.md! -fn is_in_follow(tok: "ed::TokenTree, frag: Symbol) -> IsInFollow { - use quoted::TokenTree; +fn is_in_follow(tok: &mbe::TokenTree, frag: Symbol) -> IsInFollow { + use mbe::TokenTree; if let TokenTree::Token(Token { kind: token::CloseDelim(_), .. }) = *tok { // closing a token tree can never be matched by any fragment; @@ -1116,10 +1116,10 @@ fn has_legal_fragment_specifier( sess: &ParseSess, features: &Features, attrs: &[ast::Attribute], - tok: "ed::TokenTree, + tok: &mbe::TokenTree, ) -> Result<(), String> { debug!("has_legal_fragment_specifier({:?})", tok); - if let quoted::TokenTree::MetaVarDecl(_, _, ref frag_spec) = *tok { + if let mbe::TokenTree::MetaVarDecl(_, _, ref frag_spec) = *tok { let frag_span = tok.span(); if !is_legal_fragment_specifier(sess, features, attrs, frag_spec.name, frag_span) { return Err(frag_spec.to_string()); @@ -1160,13 +1160,13 @@ fn is_legal_fragment_specifier( } } -fn quoted_tt_to_string(tt: "ed::TokenTree) -> String { +fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { match *tt { - quoted::TokenTree::Token(ref token) => crate::print::pprust::token_to_string(&token), - quoted::TokenTree::MetaVar(_, name) => format!("${}", name), - quoted::TokenTree::MetaVarDecl(_, name, kind) => format!("${}:{}", name, kind), + mbe::TokenTree::Token(ref token) => crate::print::pprust::token_to_string(&token), + mbe::TokenTree::MetaVar(_, name) => format!("${}", name), + mbe::TokenTree::MetaVarDecl(_, name, kind) => format!("${}:{}", name, kind), _ => panic!( - "unexpected quoted::TokenTree::{{Sequence or Delimited}} \ + "unexpected mbe::TokenTree::{{Sequence or Delimited}} \ in follow set checker" ), } diff --git a/src/libsyntax/ext/mbe/quoted.rs b/src/libsyntax/ext/mbe/quoted.rs index 8ef2834523112..82289d7449d36 100644 --- a/src/libsyntax/ext/mbe/quoted.rs +++ b/src/libsyntax/ext/mbe/quoted.rs @@ -1,166 +1,19 @@ use crate::ast; use crate::ast::NodeId; use crate::ext::mbe::macro_parser; +use crate::ext::mbe::{TokenTree, KleeneOp, KleeneToken, SequenceRepetition, Delimited}; use crate::feature_gate::Features; -use crate::parse::token::{self, Token, TokenKind}; +use crate::parse::token::{self, Token}; use crate::parse::ParseSess; use crate::print::pprust; use crate::symbol::kw; -use crate::tokenstream::{self, DelimSpan}; +use crate::tokenstream; -use syntax_pos::{edition::Edition, BytePos, Span}; +use syntax_pos::{edition::Edition, Span}; use rustc_data_structures::sync::Lrc; use std::iter::Peekable; -/// Contains the sub-token-trees of a "delimited" token tree, such as the contents of `(`. Note -/// that the delimiter itself might be `NoDelim`. -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] -crate struct Delimited { - crate delim: token::DelimToken, - crate tts: Vec, -} - -impl Delimited { - /// Returns a `self::TokenTree` with a `Span` corresponding to the opening delimiter. - crate fn open_tt(&self, span: Span) -> TokenTree { - let open_span = if span.is_dummy() { - span - } else { - span.with_hi(span.lo() + BytePos(self.delim.len() as u32)) - }; - TokenTree::token(token::OpenDelim(self.delim), open_span) - } - - /// Returns a `self::TokenTree` with a `Span` corresponding to the closing delimiter. - crate fn close_tt(&self, span: Span) -> TokenTree { - let close_span = if span.is_dummy() { - span - } else { - span.with_lo(span.hi() - BytePos(self.delim.len() as u32)) - }; - TokenTree::token(token::CloseDelim(self.delim), close_span) - } -} - -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] -crate struct SequenceRepetition { - /// The sequence of token trees - crate tts: Vec, - /// The optional separator - crate separator: Option, - /// Whether the sequence can be repeated zero (*), or one or more times (+) - crate kleene: KleeneToken, - /// The number of `Match`s that appear in the sequence (and subsequences) - crate num_captures: usize, -} - -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] -crate struct KleeneToken { - crate span: Span, - crate op: KleeneOp, -} - -impl KleeneToken { - crate fn new(op: KleeneOp, span: Span) -> KleeneToken { - KleeneToken { span, op } - } -} - -/// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star) -/// for token sequences. -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -crate enum KleeneOp { - /// Kleene star (`*`) for zero or more repetitions - ZeroOrMore, - /// Kleene plus (`+`) for one or more repetitions - OneOrMore, - /// Kleene optional (`?`) for zero or one reptitions - ZeroOrOne, -} - -/// Similar to `tokenstream::TokenTree`, except that `$i`, `$i:ident`, and `$(...)` -/// are "first-class" token trees. Useful for parsing macros. -#[derive(Debug, Clone, PartialEq, RustcEncodable, RustcDecodable)] -crate enum TokenTree { - Token(Token), - Delimited(DelimSpan, Lrc), - /// A kleene-style repetition sequence - Sequence(DelimSpan, Lrc), - /// e.g., `$var` - MetaVar(Span, ast::Ident), - /// e.g., `$var:expr`. This is only used in the left hand side of MBE macros. - MetaVarDecl( - Span, - ast::Ident, /* name to bind */ - ast::Ident, /* kind of nonterminal */ - ), -} - -impl TokenTree { - /// Return the number of tokens in the tree. - crate fn len(&self) -> usize { - match *self { - TokenTree::Delimited(_, ref delimed) => match delimed.delim { - token::NoDelim => delimed.tts.len(), - _ => delimed.tts.len() + 2, - }, - TokenTree::Sequence(_, ref seq) => seq.tts.len(), - _ => 0, - } - } - - /// Returns `true` if the given token tree is delimited. - crate fn is_delimited(&self) -> bool { - match *self { - TokenTree::Delimited(..) => true, - _ => false, - } - } - - /// Returns `true` if the given token tree is a token of the given kind. - crate fn is_token(&self, expected_kind: &TokenKind) -> bool { - match self { - TokenTree::Token(Token { kind: actual_kind, .. }) => actual_kind == expected_kind, - _ => false, - } - } - - /// Gets the `index`-th sub-token-tree. This only makes sense for delimited trees and sequences. - crate fn get_tt(&self, index: usize) -> TokenTree { - match (self, index) { - (&TokenTree::Delimited(_, ref delimed), _) if delimed.delim == token::NoDelim => { - delimed.tts[index].clone() - } - (&TokenTree::Delimited(span, ref delimed), _) => { - if index == 0 { - return delimed.open_tt(span.open); - } - if index == delimed.tts.len() + 1 { - return delimed.close_tt(span.close); - } - delimed.tts[index - 1].clone() - } - (&TokenTree::Sequence(_, ref seq), _) => seq.tts[index].clone(), - _ => panic!("Cannot expand a token tree"), - } - } - - /// Retrieves the `TokenTree`'s span. - crate fn span(&self) -> Span { - match *self { - TokenTree::Token(Token { span, .. }) - | TokenTree::MetaVar(span, _) - | TokenTree::MetaVarDecl(span, _, _) => span, - TokenTree::Delimited(span, _) | TokenTree::Sequence(span, _) => span.entire(), - } - } - - crate fn token(kind: TokenKind, span: Span) -> TokenTree { - TokenTree::Token(Token::new(kind, span)) - } -} - /// Takes a `tokenstream::TokenStream` and returns a `Vec`. Specifically, this /// takes a generic `TokenStream`, such as is used in the rest of the compiler, and returns a /// collection of `TokenTree` for use in parsing a macro. diff --git a/src/libsyntax/ext/mbe/transcribe.rs b/src/libsyntax/ext/mbe/transcribe.rs index 94ac1f60c6407..ba818ebd35c7f 100644 --- a/src/libsyntax/ext/mbe/transcribe.rs +++ b/src/libsyntax/ext/mbe/transcribe.rs @@ -1,7 +1,7 @@ use crate::ast::{Ident, Mac}; use crate::ext::base::ExtCtxt; +use crate::ext::mbe; use crate::ext::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch}; -use crate::ext::mbe::quoted; use crate::mut_visit::{self, MutVisitor}; use crate::parse::token::{self, NtTT, Token}; use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint}; @@ -38,22 +38,22 @@ impl Marker { /// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`). enum Frame { - Delimited { forest: Lrc, idx: usize, span: DelimSpan }, - Sequence { forest: Lrc, idx: usize, sep: Option }, + Delimited { forest: Lrc, idx: usize, span: DelimSpan }, + Sequence { forest: Lrc, idx: usize, sep: Option }, } impl Frame { /// Construct a new frame around the delimited set of tokens. - fn new(tts: Vec) -> Frame { - let forest = Lrc::new(quoted::Delimited { delim: token::NoDelim, tts }); + fn new(tts: Vec) -> Frame { + let forest = Lrc::new(mbe::Delimited { delim: token::NoDelim, tts }); Frame::Delimited { forest, idx: 0, span: DelimSpan::dummy() } } } impl Iterator for Frame { - type Item = quoted::TokenTree; + type Item = mbe::TokenTree; - fn next(&mut self) -> Option { + fn next(&mut self) -> Option { match *self { Frame::Delimited { ref forest, ref mut idx, .. } => { *idx += 1; @@ -90,7 +90,7 @@ impl Iterator for Frame { pub(super) fn transcribe( cx: &ExtCtxt<'_>, interp: &FxHashMap, - src: Vec, + src: Vec, transparency: Transparency, ) -> TokenStream { // Nothing for us to transcribe... @@ -178,7 +178,7 @@ pub(super) fn transcribe( // We are descending into a sequence. We first make sure that the matchers in the RHS // and the matches in `interp` have the same shape. Otherwise, either the caller or the // macro writer has made a mistake. - seq @ quoted::TokenTree::Sequence(..) => { + seq @ mbe::TokenTree::Sequence(..) => { match lockstep_iter_size(&seq, interp, &repeats) { LockstepIterSize::Unconstrained => { cx.span_fatal( @@ -199,7 +199,7 @@ pub(super) fn transcribe( LockstepIterSize::Constraint(len, _) => { // We do this to avoid an extra clone above. We know that this is a // sequence already. - let (sp, seq) = if let quoted::TokenTree::Sequence(sp, seq) = seq { + let (sp, seq) = if let mbe::TokenTree::Sequence(sp, seq) = seq { (sp, seq) } else { unreachable!() @@ -207,7 +207,7 @@ pub(super) fn transcribe( // Is the repetition empty? if len == 0 { - if seq.kleene.op == quoted::KleeneOp::OneOrMore { + if seq.kleene.op == mbe::KleeneOp::OneOrMore { // FIXME: this really ought to be caught at macro definition // time... It happens when the Kleene operator in the matcher and // the body for the same meta-variable do not match. @@ -232,7 +232,7 @@ pub(super) fn transcribe( } // Replace the meta-var with the matched token tree from the invocation. - quoted::TokenTree::MetaVar(mut sp, mut ident) => { + mbe::TokenTree::MetaVar(mut sp, mut ident) => { // Find the matched nonterminal from the macro invocation, and use it to replace // the meta-var. if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) { @@ -269,7 +269,7 @@ pub(super) fn transcribe( // We will produce all of the results of the inside of the `Delimited` and then we will // jump back out of the Delimited, pop the result_stack and add the new results back to // the previous results (from outside the Delimited). - quoted::TokenTree::Delimited(mut span, delimited) => { + mbe::TokenTree::Delimited(mut span, delimited) => { marker.visit_delim_span(&mut span); stack.push(Frame::Delimited { forest: delimited, idx: 0, span }); result_stack.push(mem::take(&mut result)); @@ -277,14 +277,14 @@ pub(super) fn transcribe( // Nothing much to do here. Just push the token to the result, being careful to // preserve syntax context. - quoted::TokenTree::Token(token) => { + mbe::TokenTree::Token(token) => { let mut tt = TokenTree::Token(token); marker.visit_tt(&mut tt); result.push(tt.into()); } // There should be no meta-var declarations in the invocation of a macro. - quoted::TokenTree::MetaVarDecl(..) => panic!("unexpected `TokenTree::MetaVarDecl"), + mbe::TokenTree::MetaVarDecl(..) => panic!("unexpected `TokenTree::MetaVarDecl"), } } } @@ -368,11 +368,11 @@ impl LockstepIterSize { /// `lookup_cur_matched` will return `None`, which is why this still works even in the presnece of /// multiple nested matcher sequences. fn lockstep_iter_size( - tree: "ed::TokenTree, + tree: &mbe::TokenTree, interpolations: &FxHashMap, repeats: &[(usize, usize)], ) -> LockstepIterSize { - use quoted::TokenTree; + use mbe::TokenTree; match *tree { TokenTree::Delimited(_, ref delimed) => { delimed.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| { diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index d46e38f53d51b..fd87f8a1f678a 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -14,7 +14,7 @@ //! ownership of the original. use crate::ext::base; -use crate::ext::mbe::{macro_parser, quoted}; +use crate::ext::mbe::{self, macro_parser}; use crate::parse::Directory; use crate::parse::token::{self, DelimToken, Token, TokenKind}; use crate::print::pprust; @@ -64,7 +64,7 @@ where impl TokenTree { /// Use this token tree as a matcher to parse given tts. - crate fn parse(cx: &base::ExtCtxt<'_>, mtch: &[quoted::TokenTree], tts: TokenStream) + crate fn parse(cx: &base::ExtCtxt<'_>, mtch: &[mbe::TokenTree], tts: TokenStream) -> macro_parser::NamedParseResult { // `None` is because we're not interpolating let directory = Directory { From 983569732d24df434c644dd1764e9c5e4ecfd081 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Sep 2019 19:41:04 +0300 Subject: [PATCH 079/413] push TokenTree::parse down --- src/libsyntax/ext/mbe/macro_rules.rs | 15 ++++++++++++++- src/libsyntax/tokenstream.rs | 15 --------------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/libsyntax/ext/mbe/macro_rules.rs b/src/libsyntax/ext/mbe/macro_rules.rs index 2ec171a7fb591..816baadb12fbb 100644 --- a/src/libsyntax/ext/mbe/macro_rules.rs +++ b/src/libsyntax/ext/mbe/macro_rules.rs @@ -8,7 +8,7 @@ use crate::ext::mbe; use crate::ext::mbe::macro_check; use crate::ext::mbe::macro_parser::{parse, parse_failure_msg}; use crate::ext::mbe::macro_parser::{Error, Failure, Success}; -use crate::ext::mbe::macro_parser::{MatchedNonterminal, MatchedSeq}; +use crate::ext::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedParseResult}; use crate::ext::mbe::transcribe::transcribe; use crate::feature_gate::Features; use crate::parse::parser::Parser; @@ -1171,3 +1171,16 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { ), } } + +impl TokenTree { + /// Use this token tree as a matcher to parse given tts. + fn parse(cx: &ExtCtxt<'_>, mtch: &[mbe::TokenTree], tts: TokenStream) + -> NamedParseResult { + // `None` is because we're not interpolating + let directory = Directory { + path: Cow::from(cx.current_expansion.module.directory.as_path()), + ownership: cx.current_expansion.directory_ownership, + }; + parse(cx.parse_sess(), tts, mtch, Some(directory), true) + } +} diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index fd87f8a1f678a..26cae2a8e7c42 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -13,9 +13,6 @@ //! and a borrowed `TokenStream` is sufficient to build an owned `TokenStream` without taking //! ownership of the original. -use crate::ext::base; -use crate::ext::mbe::{self, macro_parser}; -use crate::parse::Directory; use crate::parse::token::{self, DelimToken, Token, TokenKind}; use crate::print::pprust; @@ -26,7 +23,6 @@ use rustc_data_structures::sync::Lrc; use rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; use smallvec::{SmallVec, smallvec}; -use std::borrow::Cow; use std::{fmt, iter, mem}; #[cfg(test)] @@ -63,17 +59,6 @@ where {} impl TokenTree { - /// Use this token tree as a matcher to parse given tts. - crate fn parse(cx: &base::ExtCtxt<'_>, mtch: &[mbe::TokenTree], tts: TokenStream) - -> macro_parser::NamedParseResult { - // `None` is because we're not interpolating - let directory = Directory { - path: Cow::from(cx.current_expansion.module.directory.as_path()), - ownership: cx.current_expansion.directory_ownership, - }; - macro_parser::parse(cx.parse_sess(), tts, mtch, Some(directory), true) - } - /// Checks if this TokenTree is equal to the other, regardless of span information. pub fn eq_unspanned(&self, other: &TokenTree) -> bool { match (self, other) { From 81fe85710d7f749c87494c4b968861adc67a9c4a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Sep 2019 19:42:52 +0300 Subject: [PATCH 080/413] make mbe::TokenTree private to module --- src/libsyntax/ext/mbe.rs | 44 +++++++++++++-------------- src/libsyntax/ext/mbe/macro_check.rs | 2 +- src/libsyntax/ext/mbe/macro_parser.rs | 4 +-- src/libsyntax/ext/mbe/quoted.rs | 2 +- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/libsyntax/ext/mbe.rs b/src/libsyntax/ext/mbe.rs index c18b8918ff1e3..a87da791c9b4f 100644 --- a/src/libsyntax/ext/mbe.rs +++ b/src/libsyntax/ext/mbe.rs @@ -20,14 +20,14 @@ use rustc_data_structures::sync::Lrc; /// Contains the sub-token-trees of a "delimited" token tree, such as the contents of `(`. Note /// that the delimiter itself might be `NoDelim`. #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] -crate struct Delimited { - crate delim: token::DelimToken, - crate tts: Vec, +struct Delimited { + delim: token::DelimToken, + tts: Vec, } impl Delimited { /// Returns a `self::TokenTree` with a `Span` corresponding to the opening delimiter. - crate fn open_tt(&self, span: Span) -> TokenTree { + fn open_tt(&self, span: Span) -> TokenTree { let open_span = if span.is_dummy() { span } else { @@ -37,7 +37,7 @@ impl Delimited { } /// Returns a `self::TokenTree` with a `Span` corresponding to the closing delimiter. - crate fn close_tt(&self, span: Span) -> TokenTree { + fn close_tt(&self, span: Span) -> TokenTree { let close_span = if span.is_dummy() { span } else { @@ -48,25 +48,25 @@ impl Delimited { } #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] -crate struct SequenceRepetition { +struct SequenceRepetition { /// The sequence of token trees - crate tts: Vec, + tts: Vec, /// The optional separator - crate separator: Option, + separator: Option, /// Whether the sequence can be repeated zero (*), or one or more times (+) - crate kleene: KleeneToken, + kleene: KleeneToken, /// The number of `Match`s that appear in the sequence (and subsequences) - crate num_captures: usize, + num_captures: usize, } #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)] -crate struct KleeneToken { - crate span: Span, - crate op: KleeneOp, +struct KleeneToken { + span: Span, + op: KleeneOp, } impl KleeneToken { - crate fn new(op: KleeneOp, span: Span) -> KleeneToken { + fn new(op: KleeneOp, span: Span) -> KleeneToken { KleeneToken { span, op } } } @@ -74,7 +74,7 @@ impl KleeneToken { /// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star) /// for token sequences. #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] -crate enum KleeneOp { +enum KleeneOp { /// Kleene star (`*`) for zero or more repetitions ZeroOrMore, /// Kleene plus (`+`) for one or more repetitions @@ -86,7 +86,7 @@ crate enum KleeneOp { /// Similar to `tokenstream::TokenTree`, except that `$i`, `$i:ident`, and `$(...)` /// are "first-class" token trees. Useful for parsing macros. #[derive(Debug, Clone, PartialEq, RustcEncodable, RustcDecodable)] -crate enum TokenTree { +enum TokenTree { Token(Token), Delimited(DelimSpan, Lrc), /// A kleene-style repetition sequence @@ -103,7 +103,7 @@ crate enum TokenTree { impl TokenTree { /// Return the number of tokens in the tree. - crate fn len(&self) -> usize { + fn len(&self) -> usize { match *self { TokenTree::Delimited(_, ref delimed) => match delimed.delim { token::NoDelim => delimed.tts.len(), @@ -115,7 +115,7 @@ impl TokenTree { } /// Returns `true` if the given token tree is delimited. - crate fn is_delimited(&self) -> bool { + fn is_delimited(&self) -> bool { match *self { TokenTree::Delimited(..) => true, _ => false, @@ -123,7 +123,7 @@ impl TokenTree { } /// Returns `true` if the given token tree is a token of the given kind. - crate fn is_token(&self, expected_kind: &TokenKind) -> bool { + fn is_token(&self, expected_kind: &TokenKind) -> bool { match self { TokenTree::Token(Token { kind: actual_kind, .. }) => actual_kind == expected_kind, _ => false, @@ -131,7 +131,7 @@ impl TokenTree { } /// Gets the `index`-th sub-token-tree. This only makes sense for delimited trees and sequences. - crate fn get_tt(&self, index: usize) -> TokenTree { + fn get_tt(&self, index: usize) -> TokenTree { match (self, index) { (&TokenTree::Delimited(_, ref delimed), _) if delimed.delim == token::NoDelim => { delimed.tts[index].clone() @@ -151,7 +151,7 @@ impl TokenTree { } /// Retrieves the `TokenTree`'s span. - crate fn span(&self) -> Span { + fn span(&self) -> Span { match *self { TokenTree::Token(Token { span, .. }) | TokenTree::MetaVar(span, _) @@ -160,7 +160,7 @@ impl TokenTree { } } - crate fn token(kind: TokenKind, span: Span) -> TokenTree { + fn token(kind: TokenKind, span: Span) -> TokenTree { TokenTree::Token(Token::new(kind, span)) } } diff --git a/src/libsyntax/ext/mbe/macro_check.rs b/src/libsyntax/ext/mbe/macro_check.rs index a3750e5c46945..97074f5cbe46c 100644 --- a/src/libsyntax/ext/mbe/macro_check.rs +++ b/src/libsyntax/ext/mbe/macro_check.rs @@ -196,7 +196,7 @@ struct MacroState<'a> { /// - `node_id` is used to emit lints /// - `span` is used when no spans are available /// - `lhses` and `rhses` should have the same length and represent the macro definition -crate fn check_meta_variables( +pub(super) fn check_meta_variables( sess: &ParseSess, node_id: NodeId, span: Span, diff --git a/src/libsyntax/ext/mbe/macro_parser.rs b/src/libsyntax/ext/mbe/macro_parser.rs index 35fc6cf21b80e..b51384d3b15e1 100644 --- a/src/libsyntax/ext/mbe/macro_parser.rs +++ b/src/libsyntax/ext/mbe/macro_parser.rs @@ -282,7 +282,7 @@ crate enum ParseResult { crate type NamedParseResult = ParseResult>; /// Count how many metavars are named in the given matcher `ms`. -crate fn count_names(ms: &[TokenTree]) -> usize { +pub(super) fn count_names(ms: &[TokenTree]) -> usize { ms.iter().fold(0, |count, elt| { count + match *elt { TokenTree::Sequence(_, ref seq) => seq.num_captures, @@ -648,7 +648,7 @@ fn inner_parse_loop<'root, 'tt>( /// - `directory`: Information about the file locations (needed for the black-box parser) /// - `recurse_into_modules`: Whether or not to recurse into modules (needed for the black-box /// parser) -crate fn parse( +pub(super) fn parse( sess: &ParseSess, tts: TokenStream, ms: &[TokenTree], diff --git a/src/libsyntax/ext/mbe/quoted.rs b/src/libsyntax/ext/mbe/quoted.rs index 82289d7449d36..3952e29a5f0d1 100644 --- a/src/libsyntax/ext/mbe/quoted.rs +++ b/src/libsyntax/ext/mbe/quoted.rs @@ -35,7 +35,7 @@ use std::iter::Peekable; /// # Returns /// /// A collection of `self::TokenTree`. There may also be some errors emitted to `sess`. -crate fn parse( +pub(super) fn parse( input: tokenstream::TokenStream, expect_matchers: bool, sess: &ParseSess, From 2ae90165534f18aa5020ae84f5e3768e99139069 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 22 Sep 2019 11:27:55 -0700 Subject: [PATCH 081/413] Point at definition when misusing ADT When given `struct Foo(usize)` and using it as `Foo {}` or `Foo`, point at `Foo`'s definition in the error. --- src/librustc_resolve/late/diagnostics.rs | 22 +++++++----- .../ui/empty/empty-struct-braces-expr.stderr | 12 +++++++ .../ui/empty/empty-struct-braces-pat-1.stderr | 3 ++ .../ui/empty/empty-struct-braces-pat-2.stderr | 6 ++++ .../ui/empty/empty-struct-braces-pat-3.stderr | 6 ++++ .../ui/empty/empty-struct-tuple-pat.stderr | 7 ++-- src/test/ui/error-codes/E0423.stderr | 3 ++ src/test/ui/issues/issue-19086.stderr | 3 ++ src/test/ui/issues/issue-32004.stderr | 5 ++- src/test/ui/issues/issue-63983.stderr | 8 ++++- src/test/ui/namespace/namespace-mix.stderr | 3 ++ .../ui/parser/recover-from-bad-variant.stderr | 3 ++ src/test/ui/resolve/issue-18252.stderr | 3 ++ src/test/ui/resolve/issue-19452.stderr | 3 ++ src/test/ui/resolve/issue-39226.stderr | 3 ++ src/test/ui/resolve/issue-6702.stderr | 9 +++-- src/test/ui/resolve/privacy-enum-ctor.stderr | 36 ++++++++++++++----- .../ui/resolve/privacy-struct-ctor.stderr | 9 +++-- .../fn-or-tuple-struct-without-args.stderr | 3 ++ src/test/ui/suggestions/issue-61226.stderr | 3 ++ 20 files changed, 126 insertions(+), 24 deletions(-) diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index cd1689f21cc6e..c7385f8a99176 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -348,7 +348,7 @@ impl<'a> LateResolutionVisitor<'a, '_> { _ => false, }; - let mut bad_struct_syntax_suggestion = || { + let mut bad_struct_syntax_suggestion = |def_id: DefId| { let (followed_by_brace, closing_brace) = self.followed_by_brace(span); let mut suggested = false; match source { @@ -374,6 +374,9 @@ impl<'a> LateResolutionVisitor<'a, '_> { _ => {} } if !suggested { + if let Some(span) = self.r.definitions.opt_span(def_id) { + err.span_label(span, &format!("`{}` defined here", path_str)); + } err.span_label( span, format!("did you mean `{} {{ /* fields */ }}`?", path_str), @@ -437,18 +440,21 @@ impl<'a> LateResolutionVisitor<'a, '_> { ); } } else { - bad_struct_syntax_suggestion(); + bad_struct_syntax_suggestion(def_id); } } - (Res::Def(DefKind::Union, _), _) | - (Res::Def(DefKind::Variant, _), _) | - (Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _), _) if ns == ValueNS => { - bad_struct_syntax_suggestion(); + (Res::Def(DefKind::Union, def_id), _) | + (Res::Def(DefKind::Variant, def_id), _) | + (Res::Def(DefKind::Ctor(_, CtorKind::Fictive), def_id), _) if ns == ValueNS => { + bad_struct_syntax_suggestion(def_id); } - (Res::Def(DefKind::Ctor(_, CtorKind::Fn), _), _) if ns == ValueNS => { + (Res::Def(DefKind::Ctor(_, CtorKind::Fn), def_id), _) if ns == ValueNS => { + if let Some(span) = self.r.definitions.opt_span(def_id) { + err.span_label(span, &format!("`{}` defined here", path_str)); + } err.span_label( span, - format!("did you mean `{} ( /* fields */ )`?", path_str), + format!("did you mean `{}( /* fields */ )`?", path_str), ); } (Res::SelfTy(..), _) if ns == ValueNS => { diff --git a/src/test/ui/empty/empty-struct-braces-expr.stderr b/src/test/ui/empty/empty-struct-braces-expr.stderr index b9681db87b67e..9712157552716 100644 --- a/src/test/ui/empty/empty-struct-braces-expr.stderr +++ b/src/test/ui/empty/empty-struct-braces-expr.stderr @@ -1,6 +1,9 @@ error[E0423]: expected value, found struct `Empty1` --> $DIR/empty-struct-braces-expr.rs:15:14 | +LL | struct Empty1 {} + | ---------------- `Empty1` defined here +... LL | let e1 = Empty1; | ^^^^^^ | | @@ -10,6 +13,9 @@ LL | let e1 = Empty1; error[E0423]: expected function, found struct `Empty1` --> $DIR/empty-struct-braces-expr.rs:16:14 | +LL | struct Empty1 {} + | ---------------- `Empty1` defined here +... LL | let e1 = Empty1(); | ^^^^^^ | | @@ -19,12 +25,18 @@ LL | let e1 = Empty1(); error[E0423]: expected value, found struct variant `E::Empty3` --> $DIR/empty-struct-braces-expr.rs:17:14 | +LL | Empty3 {} + | --------- `E::Empty3` defined here +... LL | let e3 = E::Empty3; | ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`? error[E0423]: expected function, found struct variant `E::Empty3` --> $DIR/empty-struct-braces-expr.rs:18:14 | +LL | Empty3 {} + | --------- `E::Empty3` defined here +... LL | let e3 = E::Empty3(); | ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`? diff --git a/src/test/ui/empty/empty-struct-braces-pat-1.stderr b/src/test/ui/empty/empty-struct-braces-pat-1.stderr index 6c361c703440c..271e811a2fd65 100644 --- a/src/test/ui/empty/empty-struct-braces-pat-1.stderr +++ b/src/test/ui/empty/empty-struct-braces-pat-1.stderr @@ -1,6 +1,9 @@ error[E0532]: expected unit struct/variant or constant, found struct variant `E::Empty3` --> $DIR/empty-struct-braces-pat-1.rs:24:9 | +LL | Empty3 {} + | --------- `E::Empty3` defined here +... LL | E::Empty3 => () | ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`? diff --git a/src/test/ui/empty/empty-struct-braces-pat-2.stderr b/src/test/ui/empty/empty-struct-braces-pat-2.stderr index 12047b5880c3e..3352473788894 100644 --- a/src/test/ui/empty/empty-struct-braces-pat-2.stderr +++ b/src/test/ui/empty/empty-struct-braces-pat-2.stderr @@ -1,6 +1,9 @@ error[E0532]: expected tuple struct/variant, found struct `Empty1` --> $DIR/empty-struct-braces-pat-2.rs:15:9 | +LL | struct Empty1 {} + | ---------------- `Empty1` defined here +... LL | Empty1() => () | ^^^^^^ | | @@ -19,6 +22,9 @@ LL | XEmpty1() => () error[E0532]: expected tuple struct/variant, found struct `Empty1` --> $DIR/empty-struct-braces-pat-2.rs:21:9 | +LL | struct Empty1 {} + | ---------------- `Empty1` defined here +... LL | Empty1(..) => () | ^^^^^^ | | diff --git a/src/test/ui/empty/empty-struct-braces-pat-3.stderr b/src/test/ui/empty/empty-struct-braces-pat-3.stderr index af8731b5f0596..aefdd772b1bfd 100644 --- a/src/test/ui/empty/empty-struct-braces-pat-3.stderr +++ b/src/test/ui/empty/empty-struct-braces-pat-3.stderr @@ -1,6 +1,9 @@ error[E0532]: expected tuple struct/variant, found struct variant `E::Empty3` --> $DIR/empty-struct-braces-pat-3.rs:17:9 | +LL | Empty3 {} + | --------- `E::Empty3` defined here +... LL | E::Empty3() => () | ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`? @@ -16,6 +19,9 @@ LL | XE::XEmpty3() => () error[E0532]: expected tuple struct/variant, found struct variant `E::Empty3` --> $DIR/empty-struct-braces-pat-3.rs:25:9 | +LL | Empty3 {} + | --------- `E::Empty3` defined here +... LL | E::Empty3(..) => () | ^^^^^^^^^ did you mean `E::Empty3 { /* fields */ }`? diff --git a/src/test/ui/empty/empty-struct-tuple-pat.stderr b/src/test/ui/empty/empty-struct-tuple-pat.stderr index 6c15e7bf282ce..4b828c0d942e3 100644 --- a/src/test/ui/empty/empty-struct-tuple-pat.stderr +++ b/src/test/ui/empty/empty-struct-tuple-pat.stderr @@ -19,8 +19,11 @@ LL | XEmpty6 => () error[E0532]: expected unit struct/variant or constant, found tuple variant `E::Empty4` --> $DIR/empty-struct-tuple-pat.rs:29:9 | +LL | Empty4() + | -------- `E::Empty4` defined here +... LL | E::Empty4 => () - | ^^^^^^^^^ did you mean `E::Empty4 ( /* fields */ )`? + | ^^^^^^^^^ did you mean `E::Empty4( /* fields */ )`? error[E0532]: expected unit struct/variant or constant, found tuple variant `XE::XEmpty5` --> $DIR/empty-struct-tuple-pat.rs:33:9 @@ -29,7 +32,7 @@ LL | XE::XEmpty5 => (), | ^^^^------- | | | | | help: a unit variant with a similar name exists: `XEmpty4` - | did you mean `XE::XEmpty5 ( /* fields */ )`? + | did you mean `XE::XEmpty5( /* fields */ )`? error: aborting due to 4 previous errors diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr index ec240003f9182..ce631ca4bf786 100644 --- a/src/test/ui/error-codes/E0423.stderr +++ b/src/test/ui/error-codes/E0423.stderr @@ -27,6 +27,9 @@ LL | for _ in (std::ops::Range { start: 0, end: 10 }) {} error[E0423]: expected function, found struct `Foo` --> $DIR/E0423.rs:4:13 | +LL | struct Foo { a: bool }; + | ---------------------- `Foo` defined here +LL | LL | let f = Foo(); | ^^^ | | diff --git a/src/test/ui/issues/issue-19086.stderr b/src/test/ui/issues/issue-19086.stderr index d2b9b90890e3c..e2229cbc20922 100644 --- a/src/test/ui/issues/issue-19086.stderr +++ b/src/test/ui/issues/issue-19086.stderr @@ -1,6 +1,9 @@ error[E0532]: expected tuple struct/variant, found struct variant `FooB` --> $DIR/issue-19086.rs:10:9 | +LL | FooB { x: i32, y: i32 } + | ----------------------- `FooB` defined here +... LL | FooB(a, b) => println!("{} {}", a, b), | ^^^^ did you mean `FooB { /* fields */ }`? diff --git a/src/test/ui/issues/issue-32004.stderr b/src/test/ui/issues/issue-32004.stderr index b56fa949acb7e..e9a5e217392a6 100644 --- a/src/test/ui/issues/issue-32004.stderr +++ b/src/test/ui/issues/issue-32004.stderr @@ -1,11 +1,14 @@ error[E0532]: expected unit struct/variant or constant, found tuple variant `Foo::Bar` --> $DIR/issue-32004.rs:10:9 | +LL | Bar(i32), + | -------- `Foo::Bar` defined here +... LL | Foo::Bar => {} | ^^^^^--- | | | | | help: a unit variant with a similar name exists: `Baz` - | did you mean `Foo::Bar ( /* fields */ )`? + | did you mean `Foo::Bar( /* fields */ )`? error[E0532]: expected tuple struct/variant, found unit struct `S` --> $DIR/issue-32004.rs:16:9 diff --git a/src/test/ui/issues/issue-63983.stderr b/src/test/ui/issues/issue-63983.stderr index 67acd1d57c27a..8949c475b6f72 100644 --- a/src/test/ui/issues/issue-63983.stderr +++ b/src/test/ui/issues/issue-63983.stderr @@ -1,12 +1,18 @@ error[E0532]: expected unit struct/variant or constant, found tuple variant `MyEnum::Tuple` --> $DIR/issue-63983.rs:8:9 | +LL | Tuple(i32), + | ---------- `MyEnum::Tuple` defined here +... LL | MyEnum::Tuple => "", - | ^^^^^^^^^^^^^ did you mean `MyEnum::Tuple ( /* fields */ )`? + | ^^^^^^^^^^^^^ did you mean `MyEnum::Tuple( /* fields */ )`? error[E0532]: expected unit struct/variant or constant, found struct variant `MyEnum::Struct` --> $DIR/issue-63983.rs:10:9 | +LL | Struct{ s: i32 }, + | ---------------- `MyEnum::Struct` defined here +... LL | MyEnum::Struct => "", | ^^^^^^^^^^^^^^ did you mean `MyEnum::Struct { /* fields */ }`? diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr index 249ad1c584421..900e9cf54c97a 100644 --- a/src/test/ui/namespace/namespace-mix.stderr +++ b/src/test/ui/namespace/namespace-mix.stderr @@ -37,6 +37,9 @@ LL | use namespace_mix::xm2::S; error[E0423]: expected value, found struct variant `m7::V` --> $DIR/namespace-mix.rs:100:11 | +LL | V {}, + | ---- `m7::V` defined here +... LL | check(m7::V); | ^^^^^ did you mean `m7::V { /* fields */ }`? help: a tuple variant with a similar name exists diff --git a/src/test/ui/parser/recover-from-bad-variant.stderr b/src/test/ui/parser/recover-from-bad-variant.stderr index b46d3ca9c233c..32bb88d31c4c7 100644 --- a/src/test/ui/parser/recover-from-bad-variant.stderr +++ b/src/test/ui/parser/recover-from-bad-variant.stderr @@ -12,6 +12,9 @@ LL | let x = Enum::Foo(a: 3, b: 4); error[E0532]: expected tuple struct/variant, found struct variant `Enum::Foo` --> $DIR/recover-from-bad-variant.rs:10:9 | +LL | Foo { a: usize, b: usize }, + | -------------------------- `Enum::Foo` defined here +... LL | Enum::Foo(a, b) => {} | ^^^^^^^^^ did you mean `Enum::Foo { /* fields */ }`? diff --git a/src/test/ui/resolve/issue-18252.stderr b/src/test/ui/resolve/issue-18252.stderr index 293f290f82fd9..c76e5ef8b3617 100644 --- a/src/test/ui/resolve/issue-18252.stderr +++ b/src/test/ui/resolve/issue-18252.stderr @@ -1,6 +1,9 @@ error[E0423]: expected function, found struct variant `Foo::Variant` --> $DIR/issue-18252.rs:6:13 | +LL | Variant { x: usize } + | -------------------- `Foo::Variant` defined here +... LL | let f = Foo::Variant(42); | ^^^^^^^^^^^^ did you mean `Foo::Variant { /* fields */ }`? diff --git a/src/test/ui/resolve/issue-19452.stderr b/src/test/ui/resolve/issue-19452.stderr index 56a0e397b854c..4d20f1580264c 100644 --- a/src/test/ui/resolve/issue-19452.stderr +++ b/src/test/ui/resolve/issue-19452.stderr @@ -1,6 +1,9 @@ error[E0423]: expected value, found struct variant `Homura::Madoka` --> $DIR/issue-19452.rs:10:18 | +LL | Madoka { age: u32 } + | ------------------- `Homura::Madoka` defined here +... LL | let homura = Homura::Madoka; | ^^^^^^^^^^^^^^ did you mean `Homura::Madoka { /* fields */ }`? diff --git a/src/test/ui/resolve/issue-39226.stderr b/src/test/ui/resolve/issue-39226.stderr index c97fb4db6be6b..d9a28e63dce8b 100644 --- a/src/test/ui/resolve/issue-39226.stderr +++ b/src/test/ui/resolve/issue-39226.stderr @@ -1,6 +1,9 @@ error[E0423]: expected value, found struct `Handle` --> $DIR/issue-39226.rs:11:17 | +LL | struct Handle {} + | ---------------- `Handle` defined here +... LL | handle: Handle | ^^^^^^ | | diff --git a/src/test/ui/resolve/issue-6702.stderr b/src/test/ui/resolve/issue-6702.stderr index 9a46f0d774262..3fdc7acb274e5 100644 --- a/src/test/ui/resolve/issue-6702.stderr +++ b/src/test/ui/resolve/issue-6702.stderr @@ -1,8 +1,13 @@ error[E0423]: expected function, found struct `Monster` --> $DIR/issue-6702.rs:7:14 | -LL | let _m = Monster(); - | ^^^^^^^ did you mean `Monster { /* fields */ }`? +LL | / struct Monster { +LL | | damage: isize +LL | | } + | |_- `Monster` defined here +... +LL | let _m = Monster(); + | ^^^^^^^ did you mean `Monster { /* fields */ }`? error: aborting due to previous error diff --git a/src/test/ui/resolve/privacy-enum-ctor.stderr b/src/test/ui/resolve/privacy-enum-ctor.stderr index 2538bbbf8067f..7d8d1d0abfc21 100644 --- a/src/test/ui/resolve/privacy-enum-ctor.stderr +++ b/src/test/ui/resolve/privacy-enum-ctor.stderr @@ -33,8 +33,13 @@ LL | m::Z::Unit; error[E0423]: expected value, found struct variant `Z::Struct` --> $DIR/privacy-enum-ctor.rs:29:20 | -LL | let _: Z = Z::Struct; - | ^^^^^^^^^ did you mean `Z::Struct { /* fields */ }`? +LL | / Struct { +LL | | s: u8, +LL | | }, + | |_____________- `Z::Struct` defined here +... +LL | let _: Z = Z::Struct; + | ^^^^^^^^^ did you mean `Z::Struct { /* fields */ }`? error[E0423]: expected value, found enum `m::E` --> $DIR/privacy-enum-ctor.rs:41:16 @@ -63,8 +68,13 @@ LL | use std::f64::consts::E; error[E0423]: expected value, found struct variant `m::E::Struct` --> $DIR/privacy-enum-ctor.rs:45:16 | -LL | let _: E = m::E::Struct; - | ^^^^^^^^^^^^ did you mean `m::E::Struct { /* fields */ }`? +LL | / Struct { +LL | | s: u8, +LL | | }, + | |_________- `m::E::Struct` defined here +... +LL | let _: E = m::E::Struct; + | ^^^^^^^^^^^^ did you mean `m::E::Struct { /* fields */ }`? error[E0423]: expected value, found enum `E` --> $DIR/privacy-enum-ctor.rs:49:16 @@ -89,8 +99,13 @@ LL | use std::f64::consts::E; error[E0423]: expected value, found struct variant `E::Struct` --> $DIR/privacy-enum-ctor.rs:53:16 | -LL | let _: E = E::Struct; - | ^^^^^^^^^ did you mean `E::Struct { /* fields */ }`? +LL | / Struct { +LL | | s: u8, +LL | | }, + | |_________- `E::Struct` defined here +... +LL | let _: E = E::Struct; + | ^^^^^^^^^ did you mean `E::Struct { /* fields */ }`? error[E0412]: cannot find type `Z` in this scope --> $DIR/privacy-enum-ctor.rs:57:12 @@ -151,8 +166,13 @@ LL | use m::n::Z; error[E0423]: expected value, found struct variant `m::n::Z::Struct` --> $DIR/privacy-enum-ctor.rs:64:16 | -LL | let _: Z = m::n::Z::Struct; - | ^^^^^^^^^^^^^^^ did you mean `m::n::Z::Struct { /* fields */ }`? +LL | / Struct { +LL | | s: u8, +LL | | }, + | |_____________- `m::n::Z::Struct` defined here +... +LL | let _: Z = m::n::Z::Struct; + | ^^^^^^^^^^^^^^^ did you mean `m::n::Z::Struct { /* fields */ }`? error[E0412]: cannot find type `Z` in this scope --> $DIR/privacy-enum-ctor.rs:68:12 diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr index 72d62fe45ce74..979367bc623fd 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.stderr +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -16,8 +16,13 @@ LL | S; error[E0423]: expected value, found struct `S2` --> $DIR/privacy-struct-ctor.rs:38:5 | -LL | S2; - | ^^ did you mean `S2 { /* fields */ }`? +LL | / pub struct S2 { +LL | | s: u8 +LL | | } + | |_____- `S2` defined here +... +LL | S2; + | ^^ did you mean `S2 { /* fields */ }`? error[E0423]: expected value, found struct `xcrate::S` --> $DIR/privacy-struct-ctor.rs:43:5 diff --git a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr index 28b331bdbdcbc..1af0f7a191e80 100644 --- a/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr +++ b/src/test/ui/suggestions/fn-or-tuple-struct-without-args.stderr @@ -1,6 +1,9 @@ error[E0423]: expected value, found struct variant `E::B` --> $DIR/fn-or-tuple-struct-without-args.rs:36:16 | +LL | B { a: usize }, + | -------------- `E::B` defined here +... LL | let _: E = E::B; | ^^^- | | | diff --git a/src/test/ui/suggestions/issue-61226.stderr b/src/test/ui/suggestions/issue-61226.stderr index 6d7d98ac6a16b..fbcfba6653f27 100644 --- a/src/test/ui/suggestions/issue-61226.stderr +++ b/src/test/ui/suggestions/issue-61226.stderr @@ -1,6 +1,9 @@ error[E0423]: expected value, found struct `X` --> $DIR/issue-61226.rs:3:10 | +LL | struct X {} + | ----------- `X` defined here +LL | fn main() { LL | vec![X]; //… | ^ did you mean `X { /* fields */ }`? From d91b965664c47cdf8dfa060f17f50d2fe972c2de Mon Sep 17 00:00:00 2001 From: Jakob Schikowski Date: Sun, 22 Sep 2019 22:20:30 +0200 Subject: [PATCH 082/413] libtest: Make --report-time an unstable option --- src/libtest/lib.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 17baf98875c76..e441514e59738 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -566,6 +566,13 @@ pub fn parse_opts(args: &[String]) -> Option { )); } + let report_time = matches.opt_present("report-time"); + if !allow_unstable && report_time { + return Some(Err( + "The \"report-time\" flag is only accepted on the nightly compiler".into(), + )); + } + let run_ignored = match (include_ignored, matches.opt_present("ignored")) { (true, true) => { return Some(Err( @@ -579,7 +586,6 @@ pub fn parse_opts(args: &[String]) -> Option { let quiet = matches.opt_present("quiet"); let exact = matches.opt_present("exact"); let list = matches.opt_present("list"); - let report_time = matches.opt_present("report-time"); let logfile = matches.opt_str("logfile"); let logfile = logfile.map(|s| PathBuf::from(&s)); From 4ea371e40bfff6254f66c9b35510be09de5db1e6 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Mon, 23 Sep 2019 11:57:07 +1000 Subject: [PATCH 083/413] Delete iter-order-by.md --- src/doc/unstable-book/src/iter-order-by.md | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 src/doc/unstable-book/src/iter-order-by.md diff --git a/src/doc/unstable-book/src/iter-order-by.md b/src/doc/unstable-book/src/iter-order-by.md deleted file mode 100644 index 1ed97872c881c..0000000000000 --- a/src/doc/unstable-book/src/iter-order-by.md +++ /dev/null @@ -1,9 +0,0 @@ -# `iter_order_by` - -The tracking issue for this feature is: [#64295] - -[#64295]: https://github.com/rust-lang/rust/issues/64295 - ------------------------- - -Add `cmp_by`, `partial_cmp_by` and `eq_by` methods to `Iterator` in the same vein as `max_by` and `min_by`. From 0423c2a7a35ce17b44b4c93c227177fc0fcd7217 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Thu, 19 Sep 2019 22:24:06 +0900 Subject: [PATCH 084/413] Remove unused dependencies --- Cargo.lock | 13 ------------- src/librustc_ast_borrowck/Cargo.toml | 2 -- src/librustc_codegen_ssa/Cargo.toml | 1 - src/librustc_codegen_utils/Cargo.toml | 1 - src/librustc_mir/Cargo.toml | 1 - src/librustc_plugin/Cargo.toml | 1 - src/librustc_resolve/Cargo.toml | 1 - src/librustc_save_analysis/Cargo.toml | 1 - src/librustc_traits/Cargo.toml | 2 -- src/libstd/Cargo.toml | 3 --- src/libsyntax/Cargo.toml | 1 - src/libsyntax_ext/Cargo.toml | 1 - 12 files changed, 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fa749e5e3aebe..5b446c517c915 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3325,8 +3325,6 @@ dependencies = [ "log", "rustc", "rustc_data_structures", - "rustc_errors", - "syntax", "syntax_pos", ] @@ -3348,7 +3346,6 @@ dependencies = [ "log", "memmap", "num_cpus", - "parking_lot 0.9.0", "rustc", "rustc_apfloat", "rustc_codegen_utils", @@ -3367,7 +3364,6 @@ dependencies = [ name = "rustc_codegen_utils" version = "0.0.0" dependencies = [ - "flate2", "log", "punycode", "rustc", @@ -3562,7 +3558,6 @@ name = "rustc_mir" version = "0.0.0" dependencies = [ "arena", - "byteorder", "either", "graphviz", "log", @@ -3615,7 +3610,6 @@ name = "rustc_plugin_impl" version = "0.0.0" dependencies = [ "rustc", - "rustc_errors", "rustc_metadata", "syntax", "syntax_pos", @@ -3639,7 +3633,6 @@ version = "0.0.0" dependencies = [ "arena", "bitflags", - "indexmap", "log", "rustc", "rustc_data_structures", @@ -3661,7 +3654,6 @@ dependencies = [ "rustc_codegen_utils", "rustc_data_structures", "rustc_target", - "rustc_typeck", "serde_json", "syntax", "syntax_pos", @@ -3692,9 +3684,7 @@ checksum = "b725dadae9fabc488df69a287f5a99c5eaf5d10853842a8a3dfac52476f544ee" name = "rustc_traits" version = "0.0.0" dependencies = [ - "bitflags", "chalk-engine", - "graphviz", "log", "rustc", "rustc_data_structures", @@ -4057,7 +4047,6 @@ version = "0.0.0" dependencies = [ "alloc", "backtrace", - "cc", "cfg-if", "compiler_builtins", "core", @@ -4242,7 +4231,6 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_lexer", - "rustc_macros", "rustc_target", "scoped-tls", "serialize", @@ -4258,7 +4246,6 @@ dependencies = [ "log", "rustc_data_structures", "rustc_errors", - "rustc_lexer", "rustc_target", "smallvec", "syntax", diff --git a/src/librustc_ast_borrowck/Cargo.toml b/src/librustc_ast_borrowck/Cargo.toml index 024b2640e1e8e..40c4c1fc3fee6 100644 --- a/src/librustc_ast_borrowck/Cargo.toml +++ b/src/librustc_ast_borrowck/Cargo.toml @@ -12,11 +12,9 @@ doctest = false [dependencies] log = "0.4" -syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } # for "clarity", rename the graphviz crate to dot; graphviz within `borrowck` # refers to the borrowck-specific graphviz adapter traits. dot = { path = "../libgraphviz", package = "graphviz" } rustc = { path = "../librustc" } -errors = { path = "../librustc_errors", package = "rustc_errors" } rustc_data_structures = { path = "../librustc_data_structures" } diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml index bc028d6624279..2e3666e609657 100644 --- a/src/librustc_codegen_ssa/Cargo.toml +++ b/src/librustc_codegen_ssa/Cargo.toml @@ -17,7 +17,6 @@ memmap = "0.6" log = "0.4.5" libc = "0.2.44" jobserver = "0.1.11" -parking_lot = "0.9" tempfile = "3.1" rustc_serialize = { path = "../libserialize", package = "serialize" } diff --git a/src/librustc_codegen_utils/Cargo.toml b/src/librustc_codegen_utils/Cargo.toml index 89b50c5daccae..c8c219d039a73 100644 --- a/src/librustc_codegen_utils/Cargo.toml +++ b/src/librustc_codegen_utils/Cargo.toml @@ -10,7 +10,6 @@ path = "lib.rs" test = false [dependencies] -flate2 = "1.0" log = "0.4" punycode = "0.4.0" rustc-demangle = "0.1.16" diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 0691390bead4b..f296753a0304c 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -24,6 +24,5 @@ rustc_lexer = { path = "../librustc_lexer" } rustc_serialize = { path = "../libserialize", package = "serialize" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } -byteorder = { version = "1.3" } rustc_apfloat = { path = "../librustc_apfloat" } smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } diff --git a/src/librustc_plugin/Cargo.toml b/src/librustc_plugin/Cargo.toml index 84a743ed1ad7d..3f11430dc82cb 100644 --- a/src/librustc_plugin/Cargo.toml +++ b/src/librustc_plugin/Cargo.toml @@ -15,4 +15,3 @@ rustc = { path = "../librustc" } rustc_metadata = { path = "../librustc_metadata" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } -rustc_errors = { path = "../librustc_errors" } diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml index 548f982fe3bf0..936e72ef2c571 100644 --- a/src/librustc_resolve/Cargo.toml +++ b/src/librustc_resolve/Cargo.toml @@ -12,7 +12,6 @@ doctest = false [dependencies] bitflags = "1.0" -indexmap = "1" log = "0.4" syntax = { path = "../libsyntax" } rustc = { path = "../librustc" } diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml index 88bb76d2aba3a..b89c83d630b7d 100644 --- a/src/librustc_save_analysis/Cargo.toml +++ b/src/librustc_save_analysis/Cargo.toml @@ -14,7 +14,6 @@ rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_codegen_utils = { path = "../librustc_codegen_utils" } rustc_target = { path = "../librustc_target" } -rustc_typeck = { path = "../librustc_typeck" } serde_json = "1" syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml index bb28ac839a544..b86a3a5e9639b 100644 --- a/src/librustc_traits/Cargo.toml +++ b/src/librustc_traits/Cargo.toml @@ -9,8 +9,6 @@ name = "rustc_traits" path = "lib.rs" [dependencies] -bitflags = "1.0" -graphviz = { path = "../libgraphviz" } log = { version = "0.4" } rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index af1d2402f88e7..ee4b367b5c5b9 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -53,9 +53,6 @@ fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] } [target.wasm32-wasi.dependencies] wasi = { version = "0.7.0", features = ['rustc-dep-of-std', 'alloc'] } -[build-dependencies] -cc = "1.0" - [features] default = ["std_detect_file_io", "std_detect_dlsym_getauxval"] diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml index d4a9acc1569b4..196cf4d9dfae8 100644 --- a/src/libsyntax/Cargo.toml +++ b/src/libsyntax/Cargo.toml @@ -19,6 +19,5 @@ syntax_pos = { path = "../libsyntax_pos" } errors = { path = "../librustc_errors", package = "rustc_errors" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_lexer = { path = "../librustc_lexer" } -rustc_macros = { path = "../librustc_macros" } rustc_target = { path = "../librustc_target" } smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } diff --git a/src/libsyntax_ext/Cargo.toml b/src/libsyntax_ext/Cargo.toml index 791ee94b4fa77..73310df305b32 100644 --- a/src/libsyntax_ext/Cargo.toml +++ b/src/libsyntax_ext/Cargo.toml @@ -18,4 +18,3 @@ rustc_target = { path = "../librustc_target" } smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } -rustc_lexer = { path = "../librustc_lexer" } From 5f58834fb85b6a49da05c90ff592ccff2496cefe Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 13 Sep 2019 14:21:40 -0400 Subject: [PATCH 085/413] Provide helper for synthesizing paths with resource suffix --- src/librustdoc/html/render.rs | 69 ++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 2623f8d227e14..4b281dc6a7b6d 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -212,6 +212,26 @@ crate struct SharedContext { playground: Option, } +impl Context { + fn path(&self, filename: &str) -> PathBuf { + // We use splitn vs Path::extension here because we might get a filename + // like `style.min.css` and we want to process that into + // `style-suffix.min.css`. Path::extension would just return `css` + // which would result in `style.min-suffix.css` which isn't what we + // want. + let mut iter = filename.splitn(2, '.'); + let base = iter.next().unwrap(); + let ext = iter.next().unwrap(); + let filename = format!( + "{}{}.{}", + base, + self.shared.resource_suffix, + ext, + ); + self.dst.join(&filename) + } +} + impl SharedContext { crate fn ensure_dir(&self, dst: &Path) -> Result<(), Error> { let mut dirs = self.created_dirs.borrow_mut(); @@ -530,13 +550,13 @@ fn write_shared( // Add all the static files. These may already exist, but we just // overwrite them anyway to make sure that they're fresh and up-to-date. - write_minify(&cx.shared.fs, cx.dst.join(&format!("rustdoc{}.css", cx.shared.resource_suffix)), + write_minify(&cx.shared.fs, cx.path("rustdoc.css"), static_files::RUSTDOC_CSS, options.enable_minification)?; - write_minify(&cx.shared.fs, cx.dst.join(&format!("settings{}.css", cx.shared.resource_suffix)), + write_minify(&cx.shared.fs, cx.path("settings.css"), static_files::SETTINGS_CSS, options.enable_minification)?; - write_minify(&cx.shared.fs, cx.dst.join(&format!("noscript{}.css", cx.shared.resource_suffix)), + write_minify(&cx.shared.fs, cx.path("noscript.css"), static_files::NOSCRIPT_CSS, options.enable_minification)?; @@ -548,34 +568,25 @@ fn write_shared( let content = try_err!(fs::read(&entry), &entry); let theme = try_none!(try_none!(entry.file_stem(), &entry).to_str(), &entry); let extension = try_none!(try_none!(entry.extension(), &entry).to_str(), &entry); - cx.shared.fs.write( - cx.dst.join(format!("{}{}.{}", theme, cx.shared.resource_suffix, extension)), - content.as_slice())?; + cx.shared.fs.write(cx.path(&format!("{}.{}", theme, extension)), content.as_slice())?; themes.insert(theme.to_owned()); } let write = |p, c| { cx.shared.fs.write(p, c) }; if (*cx.shared).layout.logo.is_empty() { - write(cx.dst.join(&format!("rust-logo{}.png", cx.shared.resource_suffix)), - static_files::RUST_LOGO)?; + write(cx.path("rust-log.png"), static_files::RUST_LOGO)?; } if (*cx.shared).layout.favicon.is_empty() { - write(cx.dst.join(&format!("favicon{}.ico", cx.shared.resource_suffix)), - static_files::RUST_FAVICON)?; - } - write(cx.dst.join(&format!("brush{}.svg", cx.shared.resource_suffix)), - static_files::BRUSH_SVG)?; - write(cx.dst.join(&format!("wheel{}.svg", cx.shared.resource_suffix)), - static_files::WHEEL_SVG)?; - write(cx.dst.join(&format!("down-arrow{}.svg", cx.shared.resource_suffix)), - static_files::DOWN_ARROW_SVG)?; - write_minify(&cx.shared.fs, cx.dst.join(&format!("light{}.css", cx.shared.resource_suffix)), - static_files::themes::LIGHT, - options.enable_minification)?; + write(cx.path("favicon.ico"), static_files::RUST_FAVICON)?; + } + write(cx.path("brush.svg"), static_files::BRUSH_SVG)?; + write(cx.path("wheel.svg"), static_files::WHEEL_SVG)?; + write(cx.path("down-arrow.svg"), static_files::DOWN_ARROW_SVG)?; + write_minify(&cx.shared.fs, + cx.path("light.css"), static_files::themes::LIGHT, options.enable_minification)?; themes.insert("light".to_owned()); - write_minify(&cx.shared.fs, cx.dst.join(&format!("dark{}.css", cx.shared.resource_suffix)), - static_files::themes::DARK, - options.enable_minification)?; + write_minify(&cx.shared.fs, + cx.path("dark.css"), static_files::themes::DARK, options.enable_minification)?; themes.insert("dark".to_owned()); let mut themes: Vec<&String> = themes.iter().collect(); @@ -638,16 +649,16 @@ themePicker.onblur = handleThemeButtonsBlur; theme_js.as_bytes() )?; - write_minify(&cx.shared.fs, cx.dst.join(&format!("main{}.js", cx.shared.resource_suffix)), + write_minify(&cx.shared.fs, cx.path("main.js"), static_files::MAIN_JS, options.enable_minification)?; - write_minify(&cx.shared.fs, cx.dst.join(&format!("settings{}.js", cx.shared.resource_suffix)), + write_minify(&cx.shared.fs, cx.path("settings.js"), static_files::SETTINGS_JS, options.enable_minification)?; if cx.shared.include_sources { write_minify( &cx.shared.fs, - cx.dst.join(&format!("source-script{}.js", cx.shared.resource_suffix)), + cx.path("source-script.js"), static_files::sidebar::SOURCE_SCRIPT, options.enable_minification)?; } @@ -655,7 +666,7 @@ themePicker.onblur = handleThemeButtonsBlur; { write_minify( &cx.shared.fs, - cx.dst.join(&format!("storage{}.js", cx.shared.resource_suffix)), + cx.path("storage.js"), &format!("var resourcesSuffix = \"{}\";{}", cx.shared.resource_suffix, static_files::STORAGE_JS), @@ -663,7 +674,7 @@ themePicker.onblur = handleThemeButtonsBlur; } if let Some(ref css) = cx.shared.layout.css_file_extension { - let out = cx.dst.join(&format!("theme{}.css", cx.shared.resource_suffix)); + let out = cx.path("theme.css"); let buffer = try_err!(fs::read_to_string(css), css); if !options.enable_minification { cx.shared.fs.write(&out, &buffer)?; @@ -671,7 +682,7 @@ themePicker.onblur = handleThemeButtonsBlur; write_minify(&cx.shared.fs, out, &buffer, options.enable_minification)?; } } - write_minify(&cx.shared.fs, cx.dst.join(&format!("normalize{}.css", cx.shared.resource_suffix)), + write_minify(&cx.shared.fs, cx.path("normalize.css"), static_files::NORMALIZE_CSS, options.enable_minification)?; write(cx.dst.join("FiraSans-Regular.woff"), From 61f16920b3783e91cc853c720d152be6dc94e2da Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 13 Sep 2019 14:25:56 -0400 Subject: [PATCH 086/413] Remove needless Rc> --- src/librustdoc/html/render.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 4b281dc6a7b6d..e4ace7a0211b7 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3771,12 +3771,12 @@ fn sidebar_assoc_items(it: &clean::Item) -> String { let mut used_links = FxHashSet::default(); { - let used_links_bor = Rc::new(RefCell::new(&mut used_links)); + let used_links_bor = &mut used_links; let mut ret = v.iter() .filter(|i| i.inner_impl().trait_.is_none()) .flat_map(move |i| get_methods(i.inner_impl(), false, - &mut used_links_bor.borrow_mut(), false)) + used_links_bor, false)) .collect::>(); // We want links' order to be reproducible so we don't use unstable sort. ret.sort(); From 583a81dc5e19bcc21092c8f16fd7185c357bd077 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 13 Sep 2019 14:32:59 -0400 Subject: [PATCH 087/413] Remove pointless or --- src/librustdoc/html/render.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index e4ace7a0211b7..e3f227e0cf4d6 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3405,7 +3405,7 @@ fn render_impl(w: &mut Buffer, cx: &Context, i: &Impl, link: AssocItemLink<'_>, let item_type = item.type_(); let name = item.name.as_ref().unwrap(); - let render_method_item: bool = match render_mode { + let render_method_item = match render_mode { RenderMode::Normal => true, RenderMode::ForDeref { mut_: deref_mut_ } => should_render_item(&item, deref_mut_), }; @@ -3474,7 +3474,7 @@ fn render_impl(w: &mut Buffer, cx: &Context, i: &Impl, link: AssocItemLink<'_>, _ => panic!("can't make docs for trait item with name {:?}", item.name) } - if render_method_item || render_mode == RenderMode::Normal { + if render_method_item { if !is_default_item { if let Some(t) = trait_ { // The trait item may have been stripped so we might not From 53acfc3f8a52f9d26ce3ea3cdaea00345b1e9973 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 13 Sep 2019 14:59:08 -0400 Subject: [PATCH 088/413] Utilize shared error codes rather than re-querying env --- src/librustdoc/html/render.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index e3f227e0cf4d6..e66224c0b5e00 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2123,7 +2123,7 @@ fn stability_tags(item: &clean::Item) -> String { /// documentation. fn short_stability(item: &clean::Item, cx: &Context) -> Vec { let mut stability = vec![]; - let error_codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build()); + let error_codes = cx.shared.codes; if let Some(Deprecation { note, since }) = &item.deprecation() { // We display deprecation messages for #[deprecated] and #[rustc_deprecated] From cac7e5faedc0f7adb41c8cc81ee7be56d8217fd1 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 13 Sep 2019 15:22:00 -0400 Subject: [PATCH 089/413] Remove unused arguments --- src/librustdoc/html/render.rs | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index e66224c0b5e00..301dddbbfb9b2 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1702,12 +1702,12 @@ fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer) { clean::TypedefItem(ref t, _) => item_typedef(buf, cx, item, t), clean::MacroItem(ref m) => item_macro(buf, cx, item, m), clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m), - clean::PrimitiveItem(ref p) => item_primitive(buf, cx, item, p), + clean::PrimitiveItem(_) => item_primitive(buf, cx, item), clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => item_static(buf, cx, item, i), clean::ConstantItem(ref c) => item_constant(buf, cx, item, c), clean::ForeignTypeItem => item_foreign_type(buf, cx, item), - clean::KeywordItem(ref k) => item_keyword(buf, cx, item, k), + clean::KeywordItem(_) => item_keyword(buf, cx, item), clean::OpaqueTyItem(ref e, _) => item_opaque_ty(buf, cx, item, e), clean::TraitAliasItem(ref ta) => item_trait_alias(buf, cx, item, ta), _ => { @@ -3665,11 +3665,11 @@ fn print_sidebar(cx: &Context, it: &clean::Item, buffer: &mut Buffer) { match it.inner { clean::StructItem(ref s) => sidebar_struct(buffer, it, s), clean::TraitItem(ref t) => sidebar_trait(buffer, it, t), - clean::PrimitiveItem(ref p) => sidebar_primitive(buffer, it, p), + clean::PrimitiveItem(_) => sidebar_primitive(buffer, it), clean::UnionItem(ref u) => sidebar_union(buffer, it, u), clean::EnumItem(ref e) => sidebar_enum(buffer, it, e), - clean::TypedefItem(ref t, _) => sidebar_typedef(buffer, it, t), - clean::ModuleItem(ref m) => sidebar_module(buffer, it, &m.items), + clean::TypedefItem(_, _) => sidebar_typedef(buffer, it), + clean::ModuleItem(ref m) => sidebar_module(buffer, &m.items), clean::ForeignTypeItem => sidebar_foreign_type(buffer, it), _ => (), } @@ -4038,7 +4038,7 @@ fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) { write!(buf, "
    {}
    ", sidebar) } -fn sidebar_primitive(buf: &mut Buffer, it: &clean::Item, _p: &clean::PrimitiveType) { +fn sidebar_primitive(buf: &mut Buffer, it: &clean::Item) { let sidebar = sidebar_assoc_items(it); if !sidebar.is_empty() { @@ -4046,7 +4046,7 @@ fn sidebar_primitive(buf: &mut Buffer, it: &clean::Item, _p: &clean::PrimitiveTy } } -fn sidebar_typedef(buf: &mut Buffer, it: &clean::Item, _t: &clean::Typedef) { +fn sidebar_typedef(buf: &mut Buffer, it: &clean::Item) { let sidebar = sidebar_assoc_items(it); if !sidebar.is_empty() { @@ -4138,7 +4138,7 @@ fn item_ty_to_strs(ty: &ItemType) -> (&'static str, &'static str) { } } -fn sidebar_module(buf: &mut Buffer, _it: &clean::Item, items: &[clean::Item]) { +fn sidebar_module(buf: &mut Buffer, items: &[clean::Item]) { let mut sidebar = String::new(); if items.iter().any(|it| it.type_() == ItemType::ExternCrate || @@ -4216,16 +4216,12 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, m: &clean::Pr document(w, cx, it) } -fn item_primitive(w: &mut Buffer, cx: &Context, - it: &clean::Item, - _p: &clean::PrimitiveType) { +fn item_primitive(w: &mut Buffer, cx: &Context, it: &clean::Item) { document(w, cx, it); render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } -fn item_keyword(w: &mut Buffer, cx: &Context, - it: &clean::Item, - _p: &str) { +fn item_keyword(w: &mut Buffer, cx: &Context, it: &clean::Item) { document(w, cx, it) } From 059163fad796e3ecf04c29f423b9cf985717f025 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 13 Sep 2019 16:00:36 -0400 Subject: [PATCH 090/413] Remove needless `mut` in paths --- src/librustdoc/html/render/cache.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index e9f0955c54126..65dd119c27cb7 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -548,7 +548,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { let Cache { ref mut search_index, ref orphan_impl_items, - ref mut paths, .. } = *cache; + ref paths, .. } = *cache; // Attach all orphan items to the type's definition if the type // has since been learned. From d2762acb8ce945670ee2249149a5757991591e85 Mon Sep 17 00:00:00 2001 From: Andre Richter Date: Wed, 18 Sep 2019 15:38:02 +0200 Subject: [PATCH 091/413] Differentiate AArch64 bare-metal targets between hf and non-hf. Following up on [1] and [2], this PR adds differntiation for aarch64 bare-metal targets between versions with and without hardware floating point enabled. This streamlines the target naming with other existing ARM targets and provides the user clear indication if he is getting float or non-float for his bare-metal target. [1] https://github.com/rust-lang/rust/pull/60135#issuecomment-485851356 [2] https://github.com/rust-embedded/wg/issues/230 Closes: rust-embedded/wg#230 --- .../spec/aarch64_unknown_none.rs | 4 +- .../spec/aarch64_unknown_none_softfloat.rs | 37 +++++++++++++++++++ src/librustc_target/spec/mod.rs | 1 + 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 src/librustc_target/spec/aarch64_unknown_none_softfloat.rs diff --git a/src/librustc_target/spec/aarch64_unknown_none.rs b/src/librustc_target/spec/aarch64_unknown_none.rs index 8c02bc61088b4..b9549ec2120dd 100644 --- a/src/librustc_target/spec/aarch64_unknown_none.rs +++ b/src/librustc_target/spec/aarch64_unknown_none.rs @@ -1,4 +1,4 @@ -// Generic AArch64 target for bare-metal code +// Generic AArch64 target for bare-metal code - Floating point enabled // // Can be used in conjunction with the `target-feature` and // `target-cpu` compiler flags to opt-in more hardware-specific @@ -11,7 +11,7 @@ use super::{LldFlavor, LinkerFlavor, Target, TargetOptions, PanicStrategy}; pub fn target() -> Result { let opts = TargetOptions { linker: Some("rust-lld".to_owned()), - features: "+strict-align".to_string(), + features: "+strict-align,+neon,+fp-armv8".to_string(), executables: true, relocation_model: "static".to_string(), disable_redzone: true, diff --git a/src/librustc_target/spec/aarch64_unknown_none_softfloat.rs b/src/librustc_target/spec/aarch64_unknown_none_softfloat.rs new file mode 100644 index 0000000000000..b91f2af68ecb8 --- /dev/null +++ b/src/librustc_target/spec/aarch64_unknown_none_softfloat.rs @@ -0,0 +1,37 @@ +// Generic AArch64 target for bare-metal code - Floating point disabled +// +// Can be used in conjunction with the `target-feature` and +// `target-cpu` compiler flags to opt-in more hardware-specific +// features. +// +// For example, `-C target-cpu=cortex-a53`. + +use super::{LldFlavor, LinkerFlavor, Target, TargetOptions, PanicStrategy}; + +pub fn target() -> Result { + let opts = TargetOptions { + linker: Some("rust-lld".to_owned()), + features: "+strict-align,-neon,-fp-armv8".to_string(), + executables: true, + relocation_model: "static".to_string(), + disable_redzone: true, + linker_is_gnu: true, + max_atomic_width: Some(128), + panic_strategy: PanicStrategy::Abort, + abi_blacklist: super::arm_base::abi_blacklist(), + .. Default::default() + }; + Ok(Target { + llvm_target: "aarch64-unknown-none".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + target_os: "none".to_string(), + target_env: String::new(), + target_vendor: String::new(), + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), + arch: "aarch64".to_string(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), + options: opts, + }) +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 626fa374a1bd4..25add0cc6a4be 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -489,6 +489,7 @@ supported_targets! { ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf), ("aarch64-unknown-none", aarch64_unknown_none), + ("aarch64-unknown-none-softfloat", aarch64_unknown_none_softfloat), ("x86_64-fortanix-unknown-sgx", x86_64_fortanix_unknown_sgx), From ae8b3e8fc6e95a0f68fc49338f394d670e233883 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 23 Sep 2019 04:45:21 +0200 Subject: [PATCH 092/413] Introduce a diagnostic stashing API. --- src/librustc/session/mod.rs | 1 + src/librustc_driver/lib.rs | 3 +- src/librustc_errors/diagnostic_builder.rs | 41 +++++++---- src/librustc_errors/lib.rs | 84 +++++++++++++++++++---- 4 files changed, 102 insertions(+), 27 deletions(-) diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index a24fed8f21c5a..49342d95fdb03 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -321,6 +321,7 @@ impl Session { } pub fn compile_status(&self) -> Result<(), ErrorReported> { if self.has_errors() { + self.diagnostic().emit_stashed_diagnostics(); Err(ErrorReported) } else { Ok(()) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index f99e65b4494a7..4a8681367410e 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -296,7 +296,6 @@ pub fn run_compiler( ); Ok(()) })?; - return sess.compile_status(); } else { let mut krate = compiler.parse()?.take(); pretty::visit_crate(sess, &mut krate, ppm); @@ -307,8 +306,8 @@ pub fn run_compiler( ppm, compiler.output_file().as_ref().map(|p| &**p), ); - return sess.compile_status(); } + return sess.compile_status(); } if callbacks.after_parsing(compiler) == Compilation::Stop { diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index e85388bfea29c..cc60bf89c7eca 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -1,10 +1,6 @@ -use crate::Diagnostic; -use crate::DiagnosticId; -use crate::DiagnosticStyledString; -use crate::Applicability; +use crate::{Diagnostic, DiagnosticId, DiagnosticStyledString}; +use crate::{Applicability, Level, Handler, StashKey}; -use crate::Level; -use crate::Handler; use std::fmt::{self, Debug}; use std::ops::{Deref, DerefMut}; use std::thread::panicking; @@ -117,18 +113,30 @@ impl<'a> DiagnosticBuilder<'a> { } } - /// Buffers the diagnostic for later emission, unless handler - /// has disabled such buffering. - pub fn buffer(mut self, buffered_diagnostics: &mut Vec) { + /// Stashes diagnostic for possible later improvement in a different, + /// later stage of the compiler. The diagnostic can be accessed with + /// the provided `span` and `key` through `.steal_diagnostic` on `Handler`. + /// + /// As with `buffer`, this is unless the handler has disabled such buffering. + pub fn stash(self, span: Span, key: StashKey) { + if let Some((diag, handler)) = self.into_diagnostic() { + handler.stash_diagnostic(span, key, diag); + } + } + + /// Converts the builder to a `Diagnostic` for later emission, + /// unless handler has disabled such buffering. + pub fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a Handler)> { if self.0.handler.flags.dont_buffer_diagnostics || self.0.handler.flags.treat_err_as_bug.is_some() { self.emit(); - return; + return None; } - // We need to use `ptr::read` because `DiagnosticBuilder` - // implements `Drop`. + let handler = self.0.handler; + + // We need to use `ptr::read` because `DiagnosticBuilder` implements `Drop`. let diagnostic; unsafe { diagnostic = std::ptr::read(&self.0.diagnostic); @@ -137,7 +145,14 @@ impl<'a> DiagnosticBuilder<'a> { // Logging here is useful to help track down where in logs an error was // actually emitted. debug!("buffer: diagnostic={:?}", diagnostic); - buffered_diagnostics.push(diagnostic); + + Some((diagnostic, handler)) + } + + /// Buffers the diagnostic for later emission, + /// unless handler has disabled such buffering. + pub fn buffer(self, buffered_diagnostics: &mut Vec) { + buffered_diagnostics.extend(self.into_diagnostic().map(|(diag, _)| diag)); } /// Convenience function for internal use, clients should use one of the diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 1fe5b71d7b1cf..40f63ae1eee33 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -17,7 +17,7 @@ use emitter::{Emitter, EmitterWriter}; use registry::Registry; use rustc_data_structures::sync::{self, Lrc, Lock}; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::stable_hasher::StableHasher; use std::borrow::Cow; @@ -326,6 +326,18 @@ struct HandlerInner { /// this handler. These hashes is used to avoid emitting the same error /// twice. emitted_diagnostics: FxHashSet, + + /// Stashed diagnostics emitted in one stage of the compiler that may be + /// stolen by other stages (e.g. to improve them and add more information). + /// The stashed diagnostics count towards the total error count. + /// When `.abort_if_errors()` is called, these are also emitted. + stashed_diagnostics: FxIndexMap<(Span, StashKey), Diagnostic>, +} + +/// A key denoting where from a diagnostic was stashed. +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub enum StashKey { + ItemNoType, } fn default_track_diagnostic(_: &Diagnostic) {} @@ -354,7 +366,9 @@ pub struct HandlerFlags { impl Drop for HandlerInner { fn drop(&mut self) { - if self.err_count == 0 { + self.emit_stashed_diagnostics(); + + if !self.has_errors() { let bugs = std::mem::replace(&mut self.delayed_span_bugs, Vec::new()); let has_bugs = !bugs.is_empty(); for bug in bugs { @@ -419,6 +433,7 @@ impl Handler { taught_diagnostics: Default::default(), emitted_diagnostic_codes: Default::default(), emitted_diagnostics: Default::default(), + stashed_diagnostics: Default::default(), }), } } @@ -445,6 +460,31 @@ impl Handler { inner.emitted_diagnostics = Default::default(); inner.deduplicated_err_count = 0; inner.err_count = 0; + inner.stashed_diagnostics.clear(); + } + + /// Stash a given diagnostic with the given `Span` and `StashKey` as the key for later stealing. + /// If the diagnostic with this `(span, key)` already exists, this will result in an ICE. + pub fn stash_diagnostic(&self, span: Span, key: StashKey, diag: Diagnostic) { + if let Some(old) = self.inner.borrow_mut().stashed_diagnostics.insert((span, key), diag) { + // We are removing a previously stashed diagnostic which should not happen. + // Create a builder and drop it on the floor to get an ICE. + drop(DiagnosticBuilder::new_diagnostic(self, old)); + } + } + + /// Steal a previously stashed diagnostic with the given `Span` and `StashKey` as the key. + pub fn steal_diagnostic(&self, span: Span, key: StashKey) -> Option> { + self.inner + .borrow_mut() + .stashed_diagnostics + .remove(&(span, key)) + .map(|diag| DiagnosticBuilder::new_diagnostic(self, diag)) + } + + /// Emit all stashed diagnostics. + pub fn emit_stashed_diagnostics(&self) { + self.inner.borrow_mut().emit_stashed_diagnostics(); } pub fn struct_dummy(&self) -> DiagnosticBuilder<'_> { @@ -617,11 +657,11 @@ impl Handler { } pub fn err_count(&self) -> usize { - self.inner.borrow().err_count + self.inner.borrow().err_count() } pub fn has_errors(&self) -> bool { - self.err_count() > 0 + self.inner.borrow().has_errors() } pub fn print_error_count(&self, registry: &Registry) { @@ -629,11 +669,11 @@ impl Handler { } pub fn abort_if_errors(&self) { - self.inner.borrow().abort_if_errors() + self.inner.borrow_mut().abort_if_errors() } pub fn abort_if_errors_and_should_abort(&self) { - self.inner.borrow().abort_if_errors_and_should_abort() + self.inner.borrow_mut().abort_if_errors_and_should_abort() } pub fn must_teach(&self, code: &DiagnosticId) -> bool { @@ -671,6 +711,12 @@ impl HandlerInner { self.emitter.emit_diagnostic(&db); } + /// Emit all stashed diagnostics. + fn emit_stashed_diagnostics(&mut self) { + let diags = self.stashed_diagnostics.drain(..).map(|x| x.1).collect::>(); + diags.iter().for_each(|diag| self.emit_diagnostic(diag)); + } + fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) { if diagnostic.cancelled() { return; @@ -713,10 +759,12 @@ impl HandlerInner { } fn treat_err_as_bug(&self) -> bool { - self.flags.treat_err_as_bug.map(|c| self.err_count >= c).unwrap_or(false) + self.flags.treat_err_as_bug.map(|c| self.err_count() >= c).unwrap_or(false) } fn print_error_count(&mut self, registry: &Registry) { + self.emit_stashed_diagnostics(); + let s = match self.deduplicated_err_count { 0 => return, 1 => "aborting due to previous error".to_string(), @@ -760,14 +808,26 @@ impl HandlerInner { } } - fn abort_if_errors_and_should_abort(&self) { - if self.err_count > 0 && !self.continue_after_error { + fn err_count(&self) -> usize { + self.err_count + self.stashed_diagnostics.len() + } + + fn has_errors(&self) -> bool { + self.err_count() > 0 + } + + fn abort_if_errors_and_should_abort(&mut self) { + self.emit_stashed_diagnostics(); + + if self.has_errors() && !self.continue_after_error { FatalError.raise(); } } - fn abort_if_errors(&self) { - if self.err_count > 0 { + fn abort_if_errors(&mut self) { + self.emit_stashed_diagnostics(); + + if self.has_errors() { FatalError.raise(); } } @@ -826,7 +886,7 @@ impl HandlerInner { fn panic_if_treat_err_as_bug(&self) { if self.treat_err_as_bug() { - let s = match (self.err_count, self.flags.treat_err_as_bug.unwrap_or(0)) { + let s = match (self.err_count(), self.flags.treat_err_as_bug.unwrap_or(0)) { (0, _) => return, (1, 1) => "aborting due to `-Z treat-err-as-bug=1`".to_string(), (1, _) => return, From 62d85849d0a9a828dc58a1820469daf80a2b5b52 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 23 Sep 2019 04:48:22 +0200 Subject: [PATCH 093/413] Add parser recovery for `const $ident = $expr;`. Then use the diagnostics-stealing API to stash parser errors and enrich them with type information in typeck. --- src/librustc_typeck/collect.rs | 49 ++++++++++++++------ src/libsyntax/parse/parser/item.rs | 47 +++++++++++++++++-- src/test/ui/suggestions/const-no-type.rs | 46 ++++++++++++++++++ src/test/ui/suggestions/const-no-type.stderr | 38 +++++++++++++++ 4 files changed, 164 insertions(+), 16 deletions(-) create mode 100644 src/test/ui/suggestions/const-no-type.rs create mode 100644 src/test/ui/suggestions/const-no-type.stderr diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index d2e9203779cc8..e6e0cb88fbd23 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -46,7 +46,7 @@ use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc::hir::GenericParamKind; use rustc::hir::{self, CodegenFnAttrFlags, CodegenFnAttrs, Unsafety}; -use errors::{Applicability, DiagnosticId}; +use errors::{Applicability, DiagnosticId, StashKey}; struct OnlySelfBounds(bool); @@ -1149,18 +1149,41 @@ fn infer_placeholder_type( def_id: DefId, body_id: hir::BodyId, span: Span, + item_ident: Ident, ) -> Ty<'_> { let ty = tcx.typeck_tables_of(def_id).node_type(body_id.hir_id); - let mut diag = bad_placeholder_type(tcx, span); - if ty != tcx.types.err { - diag.span_suggestion( - span, - "replace `_` with the correct type", - ty.to_string(), - Applicability::MaybeIncorrect, - ); + + // If this came from a free `const` or `static mut?` item, + // then the user may have written e.g. `const A = 42;`. + // In this case, the parser has stashed a diagnostic for + // us to improve in typeck so we do that now. + match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) { + Some(mut err) => { + // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type. + // We are typeck and have the real type, so remove that and suggest the actual type. + err.suggestions.clear(); + err.span_suggestion( + span, + "provide a type for the item", + format!("{}: {}", item_ident, ty), + Applicability::MachineApplicable, + ) + .emit(); + } + None => { + let mut diag = bad_placeholder_type(tcx, span); + if ty != tcx.types.err { + diag.span_suggestion( + span, + "replace `_` with the correct type", + ty.to_string(), + Applicability::MaybeIncorrect, + ); + } + diag.emit(); + } } - diag.emit(); + ty } @@ -1192,7 +1215,7 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option { body_id.and_then(|body_id| { if let hir::TyKind::Infer = ty.node { - Some(infer_placeholder_type(tcx, def_id, body_id, ty.span)) + Some(infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)) } else { None } @@ -1214,7 +1237,7 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option { if let hir::TyKind::Infer = ty.node { - infer_placeholder_type(tcx, def_id, body_id, ty.span) + infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident) } else { icx.to_ty(ty) } @@ -1246,7 +1269,7 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option { if let hir::TyKind::Infer = ty.node { - infer_placeholder_type(tcx, def_id, body_id, ty.span) + infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident) } else { icx.to_ty(ty) } diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index cf196645e4f7b..0d073f0cc97b1 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -24,7 +24,7 @@ use crate::symbol::{kw, sym}; use std::mem; use log::debug; use rustc_target::spec::abi::Abi; -use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; +use errors::{Applicability, DiagnosticBuilder, DiagnosticId, StashKey}; /// Whether the type alias or associated type is a concrete type or an opaque type. #[derive(Debug)] @@ -1477,10 +1477,23 @@ impl<'a> Parser<'a> { } } + /// Parse `["const" | ("static" "mut"?)] $ident ":" $ty = $expr` with + /// `["const" | ("static" "mut"?)]` already parsed and stored in `m`. + /// + /// When `m` is `"const"`, `$ident` may also be `"_"`. fn parse_item_const(&mut self, m: Option) -> PResult<'a, ItemInfo> { let id = if m.is_none() { self.parse_ident_or_underscore() } else { self.parse_ident() }?; - self.expect(&token::Colon)?; - let ty = self.parse_ty()?; + + // Parse the type of a `const` or `static mut?` item. + // That is, the `":" $ty` fragment. + let ty = if self.token == token::Eq { + self.recover_missing_const_type(id, m) + } else { + // Not `=` so expect `":"" $ty` as usual. + self.expect(&token::Colon)?; + self.parse_ty()? + }; + self.expect(&token::Eq)?; let e = self.parse_expr()?; self.expect(&token::Semi)?; @@ -1491,6 +1504,34 @@ impl<'a> Parser<'a> { Ok((id, item, None)) } + /// We were supposed to parse `:` but instead, we're already at `=`. + /// This means that the type is missing. + fn recover_missing_const_type(&mut self, id: Ident, m: Option) -> P { + // Construct the error and stash it away with the hope + // that typeck will later enrich the error with a type. + let kind = match m { + Some(Mutability::Mutable) => "static mut", + Some(Mutability::Immutable) => "static", + None => "const", + }; + let mut err = self.struct_span_err(id.span, &format!("missing type for `{}` item", kind)); + err.span_suggestion( + id.span, + "provide a type for the item", + format!("{}: ", id), + Applicability::HasPlaceholders, + ); + err.stash(id.span, StashKey::ItemNoType); + + // The user intended that the type be inferred, + // so treat this as if the user wrote e.g. `const A: _ = expr;`. + P(Ty { + node: TyKind::Infer, + span: id.span, + id: ast::DUMMY_NODE_ID, + }) + } + /// Parses `type Foo = Bar;` or returns `None` /// without modifying the parser state. fn eat_type(&mut self) -> Option> { diff --git a/src/test/ui/suggestions/const-no-type.rs b/src/test/ui/suggestions/const-no-type.rs new file mode 100644 index 0000000000000..99200a965dd21 --- /dev/null +++ b/src/test/ui/suggestions/const-no-type.rs @@ -0,0 +1,46 @@ +// In the cases below, the type is missing from the `const` and `static` items. +// +// Here, we test that we: +// +// a) Perform parser recovery. +// +// b) Emit a diagnostic with the actual inferred type to RHS of `=` as the suggestion. + +fn main() {} + +// These will not reach typeck: + +#[cfg(FALSE)] +const C2 = 42; +//~^ ERROR missing type for `const` item +//~| HELP provide a type for the item +//~| SUGGESTION C2: + +#[cfg(FALSE)] +static S2 = "abc"; +//~^ ERROR missing type for `static` item +//~| HELP provide a type for the item +//~| SUGGESTION S2: + +#[cfg(FALSE)] +static mut SM2 = "abc"; +//~^ ERROR missing type for `static mut` item +//~| HELP provide a type for the item +//~| SUGGESTION SM2: + +// These will, so the diagnostics should be stolen by typeck: + +const C = 42; +//~^ ERROR missing type for `const` item +//~| HELP provide a type for the item +//~| SUGGESTION C: i32 + +static S = Vec::::new(); +//~^ ERROR missing type for `static` item +//~| HELP provide a type for the item +//~| SUGGESTION S: std::vec::Vec + +static mut SM = "abc"; +//~^ ERROR missing type for `static mut` item +//~| HELP provide a type for the item +//~| SUGGESTION &'static str diff --git a/src/test/ui/suggestions/const-no-type.stderr b/src/test/ui/suggestions/const-no-type.stderr new file mode 100644 index 0000000000000..c4f17109dc5c7 --- /dev/null +++ b/src/test/ui/suggestions/const-no-type.stderr @@ -0,0 +1,38 @@ +error: missing type for `const` item + --> $DIR/const-no-type.rs:33:7 + | +LL | const C = 42; + | ^ help: provide a type for the item: `C: i32` + +error: missing type for `static` item + --> $DIR/const-no-type.rs:38:8 + | +LL | static S = Vec::::new(); + | ^ help: provide a type for the item: `S: std::vec::Vec` + +error: missing type for `static mut` item + --> $DIR/const-no-type.rs:43:12 + | +LL | static mut SM = "abc"; + | ^^ help: provide a type for the item: `SM: &'static str` + +error: missing type for `const` item + --> $DIR/const-no-type.rs:14:7 + | +LL | const C2 = 42; + | ^^ help: provide a type for the item: `C2: ` + +error: missing type for `static` item + --> $DIR/const-no-type.rs:20:8 + | +LL | static S2 = "abc"; + | ^^ help: provide a type for the item: `S2: ` + +error: missing type for `static mut` item + --> $DIR/const-no-type.rs:26:12 + | +LL | static mut SM2 = "abc"; + | ^^^ help: provide a type for the item: `SM2: ` + +error: aborting due to 6 previous errors + From f6c87aba328f5d648786237da70fd227642b9c20 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 15 Aug 2019 13:42:39 -0700 Subject: [PATCH 094/413] bootstrap: Add a helper for managing RUSTFLAGS Most of `bootstrap/bin/rustc.rs` doesn't need to exist with the advent of `RUSTFLAGS` (yes this is super old) so this starts by refactoring a bit to make it easier locally in the `Builder::cargo` method to append to `RUSTFLAGS` that gets down to rustc. --- src/bootstrap/builder.rs | 51 ++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index b7873fd1d3581..399130d6755a7 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -860,28 +860,16 @@ impl<'a> Builder<'a> { stage = compiler.stage; } - let mut extra_args = String::new(); + let mut rustflags = Rustflags::new(); + rustflags.env(&format!("RUSTFLAGS_STAGE_{}", stage)); if stage != 0 { - let s = env::var("RUSTFLAGS_NOT_BOOTSTRAP").unwrap_or_default(); - extra_args.push_str(&s); + rustflags.env("RUSTFLAGS_NOT_BOOTSTRAP"); } else { - let s = env::var("RUSTFLAGS_BOOTSTRAP").unwrap_or_default(); - extra_args.push_str(&s); + rustflags.env("RUSTFLAGS_BOOTSTRAP"); } if cmd == "clippy" { - extra_args.push_str("-Zforce-unstable-if-unmarked"); - } - - if !extra_args.is_empty() { - cargo.env( - "RUSTFLAGS", - format!( - "{} {}", - env::var("RUSTFLAGS").unwrap_or_default(), - extra_args - ), - ); + rustflags.arg("-Zforce-unstable-if-unmarked"); } let want_rustdoc = self.doc_tests != DocTests::No; @@ -1171,6 +1159,8 @@ impl<'a> Builder<'a> { self.ci_env.force_coloring_in_ci(&mut cargo); + cargo.env("RUSTFLAGS", &rustflags.0); + cargo } @@ -1271,3 +1261,30 @@ impl<'a> Builder<'a> { #[cfg(test)] mod tests; + +struct Rustflags(String); + +impl Rustflags { + fn new() -> Rustflags { + let mut ret = Rustflags(String::new()); + ret.env("RUSTFLAGS"); + return ret; + } + + fn env(&mut self, env: &str) { + if let Ok(s) = env::var(env) { + for part in s.split_whitespace() { + self.arg(part); + } + } + } + + fn arg(&mut self, arg: &str) -> &mut Self { + assert_eq!(arg.split_whitespace().count(), 1); + if self.0.len() > 0 { + self.0.push_str(" "); + } + self.0.push_str(arg); + self + } +} From 557e69b7caacefff1eb12f948e274debb2f4a5fd Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 15 Aug 2019 13:44:22 -0700 Subject: [PATCH 095/413] bootstrap: Delete handling of `RUSTC_METADATA_SUFFIX` This is already handled by `__CARGO_DEFAULT_LIB_METADATA` so there's no need to doubly do it. --- src/bootstrap/bin/rustc.rs | 18 +----------------- src/bootstrap/builder.rs | 18 ------------------ 2 files changed, 1 insertion(+), 35 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 84415baa3a140..e6102de187481 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -24,23 +24,7 @@ use std::str::FromStr; use std::time::Instant; fn main() { - let mut args = env::args_os().skip(1).collect::>(); - - // Append metadata suffix for internal crates. See the corresponding entry - // in bootstrap/lib.rs for details. - if let Ok(s) = env::var("RUSTC_METADATA_SUFFIX") { - for i in 1..args.len() { - // Dirty code for borrowing issues - let mut new = None; - if let Some(current_as_str) = args[i].to_str() { - if (&*args[i - 1] == "-C" && current_as_str.starts_with("metadata")) || - current_as_str.starts_with("-Cmetadata") { - new = Some(format!("{}-{}", current_as_str, s)); - } - } - if let Some(new) = new { args[i] = new.into(); } - } - } + let args = env::args_os().skip(1).collect::>(); // Detect whether or not we're a build script depending on whether --target // is passed (a bit janky...) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 399130d6755a7..6323fa94ccfc3 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -939,24 +939,6 @@ impl<'a> Builder<'a> { if !mode.is_tool() { cargo.env("RUSTC_FORCE_UNSTABLE", "1"); - - // Currently the compiler depends on crates from crates.io, and - // then other crates can depend on the compiler (e.g., proc-macro - // crates). Let's say, for example that rustc itself depends on the - // bitflags crate. If an external crate then depends on the - // bitflags crate as well, we need to make sure they don't - // conflict, even if they pick the same version of bitflags. We'll - // want to make sure that e.g., a plugin and rustc each get their - // own copy of bitflags. - - // Cargo ensures that this works in general through the -C metadata - // flag. This flag will frob the symbols in the binary to make sure - // they're different, even though the source code is the exact - // same. To solve this problem for the compiler we extend Cargo's - // already-passed -C metadata flag with our own. Our rustc.rs - // wrapper around the actual rustc will detect -C metadata being - // passed and frob it with this extra string we're passing in. - cargo.env("RUSTC_METADATA_SUFFIX", "rustc"); } if let Some(x) = self.crt_static(target) { From 4f35166f8091bfd0767f907a558d6e66d3afd492 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 15 Aug 2019 13:45:20 -0700 Subject: [PATCH 096/413] bootstrap: Move `RUSTC_BREAK_ON_ICE` out of shim This is always set, so let's just always set it elsewhere to reduce the need for our `rustc.rs` shim. --- src/bootstrap/bin/rustc.rs | 2 -- src/bootstrap/builder.rs | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index e6102de187481..efbfc3796ae24 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -97,8 +97,6 @@ fn main() { cmd.env("RUST_BACKTRACE", "1"); } - cmd.env("RUSTC_BREAK_ON_ICE", "1"); - if let Ok(debuginfo_level) = env::var("RUSTC_DEBUGINFO_LEVEL") { cmd.arg(format!("-Cdebuginfo={}", debuginfo_level)); } diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 6323fa94ccfc3..0704ff3ca9bc2 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -917,7 +917,8 @@ impl<'a> Builder<'a> { PathBuf::from("/path/to/nowhere/rustdoc/not/required") }, ) - .env("RUSTC_ERROR_METADATA_DST", self.extended_error_dir()); + .env("RUSTC_ERROR_METADATA_DST", self.extended_error_dir()) + .env("RUSTC_BREAK_ON_ICE", "1"); if let Some(host_linker) = self.linker(compiler.host) { cargo.env("RUSTC_HOST_LINKER", host_linker); From 812117af532d1eb8fd90c789f5cafe3c45b80437 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 15 Aug 2019 13:46:07 -0700 Subject: [PATCH 097/413] bootstrap: Move `-Zexternal-macro-backtrace` to builder No need for this to be in `rustc.rs` --- src/bootstrap/bin/rustc.rs | 2 -- src/bootstrap/builder.rs | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index efbfc3796ae24..3c836ce261d0e 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -124,8 +124,6 @@ fn main() { cmd.arg("--sysroot").arg(&sysroot); } - cmd.arg("-Zexternal-macro-backtrace"); - // Link crates to the proc macro crate for the target, but use a host proc macro crate // to actually run the macros if env::var_os("RUST_DUAL_PROC_MACROS").is_some() { diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 0704ff3ca9bc2..5481e3d86e4d8 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -872,6 +872,8 @@ impl<'a> Builder<'a> { rustflags.arg("-Zforce-unstable-if-unmarked"); } + rustflags.arg("-Zexternal-macro-backtrace"); + let want_rustdoc = self.doc_tests != DocTests::No; // We synthetically interpret a stage0 compiler used to build tools as a From c36849a542cdff30f7eaa829433f31d4bcb79c56 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 15 Aug 2019 13:46:54 -0700 Subject: [PATCH 098/413] bootstrap: Move `-Zdual-proc-macros` to `builder.rs` --- src/bootstrap/bin/rustc.rs | 6 ------ src/bootstrap/builder.rs | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 3c836ce261d0e..1955ca4aa99e5 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -124,12 +124,6 @@ fn main() { cmd.arg("--sysroot").arg(&sysroot); } - // Link crates to the proc macro crate for the target, but use a host proc macro crate - // to actually run the macros - if env::var_os("RUST_DUAL_PROC_MACROS").is_some() { - cmd.arg("-Zdual-proc-macros"); - } - // When we build Rust dylibs they're all intended for intermediate // usage, so make sure we pass the -Cprefer-dynamic flag instead of // linking all deps statically into the dylib. diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 5481e3d86e4d8..ee62b397678f5 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -802,7 +802,7 @@ impl<'a> Builder<'a> { // Build proc macros both for the host and the target if target != compiler.host && cmd != "check" { cargo.arg("-Zdual-proc-macros"); - cargo.env("RUST_DUAL_PROC_MACROS", "1"); + rustflags.arg("-Zdual-proc-macros"); } }, } From d63e2def82f208f8c15c78db5f0f58cc14792972 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 15 Aug 2019 13:51:47 -0700 Subject: [PATCH 099/413] bootstrap: Remove usage of `RUSTC_TARGET_LINKER` Cargo has a native enviroment variable for this. --- src/bootstrap/bin/rustc.rs | 5 ----- src/bootstrap/builder.rs | 3 ++- src/bootstrap/lib.rs | 10 ++++++++++ src/bootstrap/test.rs | 12 +----------- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 1955ca4aa99e5..d0d995d704eb8 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -148,11 +148,6 @@ fn main() { cmd.arg("-L").arg(&root); } - // Override linker if necessary. - if let Ok(target_linker) = env::var("RUSTC_TARGET_LINKER") { - cmd.arg(format!("-Clinker={}", target_linker)); - } - // If we're compiling specifically the `panic_abort` crate then we pass // the `-C panic=abort` option. Note that we do not do this for any // other crate intentionally as this is the only crate for now that we diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index ee62b397678f5..a7e9b9aaf64f0 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -926,7 +926,8 @@ impl<'a> Builder<'a> { cargo.env("RUSTC_HOST_LINKER", host_linker); } if let Some(target_linker) = self.linker(target) { - cargo.env("RUSTC_TARGET_LINKER", target_linker); + let target = crate::envify(&target); + cargo.env(&format!("CARGO_TARGET_{}_LINKER", target), target_linker); } if !(["build", "check", "clippy", "fix", "rustc"].contains(&cmd)) && want_rustdoc { cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler)); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 5d7581c8211be..9203a558f6465 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -1320,3 +1320,13 @@ impl Compiler { self.stage >= final_stage } } + +fn envify(s: &str) -> String { + s.chars() + .map(|c| match c { + '-' => '_', + c => c, + }) + .flat_map(|c| c.to_uppercase()) + .collect() +} diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 00d87f3841cff..37718ed89c17f 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -23,7 +23,7 @@ use crate::tool::{self, Tool, SourceType}; use crate::toolstate::ToolState; use crate::util::{self, dylib_path, dylib_path_var}; use crate::Crate as CargoCrate; -use crate::{DocTests, Mode, GitRepo}; +use crate::{DocTests, Mode, GitRepo, envify}; const ADB_TEST_DIR: &str = "/data/tmp/work"; @@ -1913,16 +1913,6 @@ impl Step for CrateRustdoc { } } -fn envify(s: &str) -> String { - s.chars() - .map(|c| match c { - '-' => '_', - c => c, - }) - .flat_map(|c| c.to_uppercase()) - .collect() -} - /// Some test suites are run inside emulators or on remote devices, and most /// of our test binaries are linked dynamically which means we need to ship /// the standard library and such to the emulator ahead of time. This step From 04cb0653a8c3577ed43bb2e365582be227be4d00 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 15 Aug 2019 13:54:36 -0700 Subject: [PATCH 100/413] bootstrap: Remove need for RUSTC_SAVE_ANALYSIS --- src/bootstrap/bin/rustc.rs | 9 --------- src/bootstrap/builder.rs | 37 ++++++++++++++++++++----------------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index d0d995d704eb8..60f4b98d9d840 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -184,15 +184,6 @@ fn main() { cmd.arg("-C").arg(format!("codegen-units={}", s)); } - // Emit save-analysis info. - if env::var("RUSTC_SAVE_ANALYSIS") == Ok("api".to_string()) { - cmd.arg("-Zsave-analysis"); - cmd.env("RUST_SAVE_ANALYSIS_CONFIG", - "{\"output_file\": null,\"full_docs\": false,\ - \"pub_only\": true,\"reachable_only\": false,\ - \"distro_crate\": true,\"signatures\": false,\"borrow_data\": false}"); - } - // Dealing with rpath here is a little special, so let's go into some // detail. First off, `-rpath` is a linker option on Unix platforms // which adds to the runtime dynamic loader path when looking for diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index a7e9b9aaf64f0..3995ab170d12e 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -796,6 +796,21 @@ impl<'a> Builder<'a> { cargo.env("RUST_CHECK", "1"); } + let stage; + if compiler.stage == 0 && self.local_rebuild { + // Assume the local-rebuild rustc already has stage1 features. + stage = 1; + } else { + stage = compiler.stage; + } + + let mut rustflags = Rustflags::new(); + if stage != 0 { + rustflags.env("RUSTFLAGS_NOT_BOOTSTRAP"); + } else { + rustflags.env("RUSTFLAGS_BOOTSTRAP"); + } + match mode { Mode::Std | Mode::ToolBootstrap | Mode::ToolStd => {}, Mode::Rustc | Mode::Codegen | Mode::ToolRustc => { @@ -852,22 +867,6 @@ impl<'a> Builder<'a> { } cargo.env("__CARGO_DEFAULT_LIB_METADATA", &metadata); - let stage; - if compiler.stage == 0 && self.local_rebuild { - // Assume the local-rebuild rustc already has stage1 features. - stage = 1; - } else { - stage = compiler.stage; - } - - let mut rustflags = Rustflags::new(); - rustflags.env(&format!("RUSTFLAGS_STAGE_{}", stage)); - if stage != 0 { - rustflags.env("RUSTFLAGS_NOT_BOOTSTRAP"); - } else { - rustflags.env("RUSTFLAGS_BOOTSTRAP"); - } - if cmd == "clippy" { rustflags.arg("-Zforce-unstable-if-unmarked"); } @@ -1064,7 +1063,11 @@ impl<'a> Builder<'a> { && self.config.extended && compiler.is_final_stage(self) { - cargo.env("RUSTC_SAVE_ANALYSIS", "api".to_string()); + rustflags.arg("-Zsave-analysis"); + cargo.env("RUST_SAVE_ANALYSIS_CONFIG", + "{\"output_file\": null,\"full_docs\": false,\ + \"pub_only\": true,\"reachable_only\": false,\ + \"distro_crate\": true,\"signatures\": false,\"borrow_data\": false}"); } // For `cargo doc` invocations, make rustdoc print the Rust version into the docs From ac29809940ca0d1ffb864975fea2d61a3d649b8d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 15 Aug 2019 13:57:09 -0700 Subject: [PATCH 101/413] bootstrap: Move `RUSTC_CRT_STATIC` to `builder.rs` --- src/bootstrap/bin/rustc.rs | 9 ++------- src/bootstrap/builder.rs | 6 +++++- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 60f4b98d9d840..c6ac03baefd8d 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -232,13 +232,8 @@ fn main() { } } - if let Ok(s) = env::var("RUSTC_CRT_STATIC") { - if s == "true" { - cmd.arg("-C").arg("target-feature=+crt-static"); - } - if s == "false" { - cmd.arg("-C").arg("target-feature=-crt-static"); - } + if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") { + cmd.arg("--remap-path-prefix").arg(&map); } } else { // Override linker if necessary. diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 3995ab170d12e..e25c4d065cfd0 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -945,7 +945,11 @@ impl<'a> Builder<'a> { } if let Some(x) = self.crt_static(target) { - cargo.env("RUSTC_CRT_STATIC", x.to_string()); + if x { + rustflags.arg("-Ctarget-feature=+crt-static"); + } else { + rustflags.arg("-Ctarget-feature=-crt-static"); + } } if let Some(x) = self.crt_static(compiler.host) { From b82d86ed60e92ad9e0aa14fc52db25d0b9d23440 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 9 Sep 2019 09:20:29 -0700 Subject: [PATCH 102/413] bootstrap: Handle target-specific cargo env vars This commit ensure that we handle target-specific env vars for RUSTFLAGS through Cargo as well. --- src/bootstrap/builder.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index e25c4d065cfd0..bf7f5313f4df1 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -804,7 +804,7 @@ impl<'a> Builder<'a> { stage = compiler.stage; } - let mut rustflags = Rustflags::new(); + let mut rustflags = Rustflags::new(&target, &mut cargo); if stage != 0 { rustflags.env("RUSTFLAGS_NOT_BOOTSTRAP"); } else { @@ -1258,9 +1258,19 @@ mod tests; struct Rustflags(String); impl Rustflags { - fn new() -> Rustflags { + fn new(target: &str, cmd: &mut Command) -> Rustflags { let mut ret = Rustflags(String::new()); + + // Inherit `RUSTFLAGS` by default ret.env("RUSTFLAGS"); + + // ... and also handle target-specific env RUSTFLAGS if they're + // configured. If this is configured we also remove it from the + // environment because Cargo will prefer it over RUSTFLAGS. + let target_specific = format!("CARGO_TARGET_{}_RUSTFLAGS", crate::envify(target)); + ret.env(&target_specific); + cmd.env_remove(&target_specific); + return ret; } From 1bec962f4687eacb09bf12955c93f6edfd6efee8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 15 Aug 2019 13:58:30 -0700 Subject: [PATCH 103/413] bootstrap: Remove need for `RUSTC_RPATH` variable --- src/bootstrap/bin/rustc.rs | 48 ------------------------------------- src/bootstrap/builder.rs | 49 +++++++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 49 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index c6ac03baefd8d..8be70c5a28713 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -184,54 +184,6 @@ fn main() { cmd.arg("-C").arg(format!("codegen-units={}", s)); } - // Dealing with rpath here is a little special, so let's go into some - // detail. First off, `-rpath` is a linker option on Unix platforms - // which adds to the runtime dynamic loader path when looking for - // dynamic libraries. We use this by default on Unix platforms to ensure - // that our nightlies behave the same on Windows, that is they work out - // of the box. This can be disabled, of course, but basically that's why - // we're gated on RUSTC_RPATH here. - // - // Ok, so the astute might be wondering "why isn't `-C rpath` used - // here?" and that is indeed a good question to task. This codegen - // option is the compiler's current interface to generating an rpath. - // Unfortunately it doesn't quite suffice for us. The flag currently - // takes no value as an argument, so the compiler calculates what it - // should pass to the linker as `-rpath`. This unfortunately is based on - // the **compile time** directory structure which when building with - // Cargo will be very different than the runtime directory structure. - // - // All that's a really long winded way of saying that if we use - // `-Crpath` then the executables generated have the wrong rpath of - // something like `$ORIGIN/deps` when in fact the way we distribute - // rustc requires the rpath to be `$ORIGIN/../lib`. - // - // So, all in all, to set up the correct rpath we pass the linker - // argument manually via `-C link-args=-Wl,-rpath,...`. Plus isn't it - // fun to pass a flag to a tool to pass a flag to pass a flag to a tool - // to change a flag in a binary? - if env::var("RUSTC_RPATH") == Ok("true".to_string()) { - let rpath = if target.contains("apple") { - - // Note that we need to take one extra step on macOS to also pass - // `-Wl,-instal_name,@rpath/...` to get things to work right. To - // do that we pass a weird flag to the compiler to get it to do - // so. Note that this is definitely a hack, and we should likely - // flesh out rpath support more fully in the future. - cmd.arg("-Z").arg("osx-rpath-install-name"); - Some("-Wl,-rpath,@loader_path/../lib") - } else if !target.contains("windows") && - !target.contains("wasm32") && - !target.contains("fuchsia") { - Some("-Wl,-rpath,$ORIGIN/../lib") - } else { - None - }; - if let Some(rpath) = rpath { - cmd.arg("-C").arg(format!("link-args={}", rpath)); - } - } - if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") { cmd.arg("--remap-path-prefix").arg(&map); } diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index bf7f5313f4df1..095770f765087 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -908,7 +908,6 @@ impl<'a> Builder<'a> { ) .env("RUSTC_SYSROOT", &sysroot) .env("RUSTC_LIBDIR", &libdir) - .env("RUSTC_RPATH", self.config.rust_rpath.to_string()) .env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc")) .env( "RUSTDOC_REAL", @@ -921,6 +920,54 @@ impl<'a> Builder<'a> { .env("RUSTC_ERROR_METADATA_DST", self.extended_error_dir()) .env("RUSTC_BREAK_ON_ICE", "1"); + // Dealing with rpath here is a little special, so let's go into some + // detail. First off, `-rpath` is a linker option on Unix platforms + // which adds to the runtime dynamic loader path when looking for + // dynamic libraries. We use this by default on Unix platforms to ensure + // that our nightlies behave the same on Windows, that is they work out + // of the box. This can be disabled, of course, but basically that's why + // we're gated on RUSTC_RPATH here. + // + // Ok, so the astute might be wondering "why isn't `-C rpath` used + // here?" and that is indeed a good question to task. This codegen + // option is the compiler's current interface to generating an rpath. + // Unfortunately it doesn't quite suffice for us. The flag currently + // takes no value as an argument, so the compiler calculates what it + // should pass to the linker as `-rpath`. This unfortunately is based on + // the **compile time** directory structure which when building with + // Cargo will be very different than the runtime directory structure. + // + // All that's a really long winded way of saying that if we use + // `-Crpath` then the executables generated have the wrong rpath of + // something like `$ORIGIN/deps` when in fact the way we distribute + // rustc requires the rpath to be `$ORIGIN/../lib`. + // + // So, all in all, to set up the correct rpath we pass the linker + // argument manually via `-C link-args=-Wl,-rpath,...`. Plus isn't it + // fun to pass a flag to a tool to pass a flag to pass a flag to a tool + // to change a flag in a binary? + if self.config.rust_rpath { + let rpath = if target.contains("apple") { + + // Note that we need to take one extra step on macOS to also pass + // `-Wl,-instal_name,@rpath/...` to get things to work right. To + // do that we pass a weird flag to the compiler to get it to do + // so. Note that this is definitely a hack, and we should likely + // flesh out rpath support more fully in the future. + rustflags.arg("-Zosx-rpath-install-name"); + Some("-Wl,-rpath,@loader_path/../lib") + } else if !target.contains("windows") && + !target.contains("wasm32") && + !target.contains("fuchsia") { + Some("-Wl,-rpath,$ORIGIN/../lib") + } else { + None + }; + if let Some(rpath) = rpath { + rustflags.arg(&format!("-Clink-args={}", rpath)); + } + } + if let Some(host_linker) = self.linker(compiler.host) { cargo.env("RUSTC_HOST_LINKER", host_linker); } From 3a648b65800c5b93531afcec873b5c2da85c8fa2 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 9 Sep 2019 09:28:07 -0700 Subject: [PATCH 104/413] Move handling of `-Dwarnings` to `builder.rs` --- src/bootstrap/bin/rustc.rs | 3 --- src/bootstrap/builder.rs | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 8be70c5a28713..9c7fba0dd7801 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -111,9 +111,6 @@ fn main() { cmd.arg("-Zunstable-options"); cmd.arg("-Wrustc::internal"); } - if env::var_os("RUSTC_DENY_WARNINGS").is_some() { - cmd.arg("-Dwarnings"); - } } if let Some(target) = target { diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 095770f765087..60673cf7cdd38 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1055,8 +1055,8 @@ impl<'a> Builder<'a> { cargo.env("RUSTC_VERBOSE", self.verbosity.to_string()); - if self.config.deny_warnings { - cargo.env("RUSTC_DENY_WARNINGS", "1"); + if self.config.deny_warnings && !mode.is_tool() { + rustflags.arg("-Dwarnings"); } // Throughout the build Cargo can execute a number of build scripts From f8b19f2b78034b058b8695409c0f87522b675a23 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 9 Sep 2019 09:29:47 -0700 Subject: [PATCH 105/413] Move handling of some warnings to `builder.rs` --- src/bootstrap/bin/rustc.rs | 5 ----- src/bootstrap/builder.rs | 12 ++++++++++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 9c7fba0dd7801..eb5b03f181d21 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -102,11 +102,6 @@ fn main() { } if env::var_os("RUSTC_EXTERNAL_TOOL").is_none() { - // When extending this list, add the new lints to the RUSTFLAGS of the - // build_bootstrap function of src/bootstrap/bootstrap.py as well as - // some code doesn't go through this `rustc` wrapper. - cmd.arg("-Wrust_2018_idioms"); - cmd.arg("-Wunused_lifetimes"); if use_internal_lints(crate_name) { cmd.arg("-Zunstable-options"); cmd.arg("-Wrustc::internal"); diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 60673cf7cdd38..e415389d307e7 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1055,8 +1055,16 @@ impl<'a> Builder<'a> { cargo.env("RUSTC_VERBOSE", self.verbosity.to_string()); - if self.config.deny_warnings && !mode.is_tool() { - rustflags.arg("-Dwarnings"); + if !mode.is_tool() { + // When extending this list, add the new lints to the RUSTFLAGS of the + // build_bootstrap function of src/bootstrap/bootstrap.py as well as + // some code doesn't go through this `rustc` wrapper. + rustflags.arg("-Wrust_2018_idioms"); + rustflags.arg("-Wunused_lifetimes"); + + if self.config.deny_warnings { + rustflags.arg("-Dwarnings"); + } } // Throughout the build Cargo can execute a number of build scripts From 22699d31394489fd42ee53ba4fcf2543ca9a1ec6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 9 Sep 2019 09:31:42 -0700 Subject: [PATCH 106/413] Move handling of internal lints to `build.rs` --- src/bootstrap/bin/rustc.rs | 15 --------------- src/bootstrap/builder.rs | 8 ++++++++ src/libserialize/lib.rs | 1 + 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index eb5b03f181d21..62ab6ef7ebe33 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -101,13 +101,6 @@ fn main() { cmd.arg(format!("-Cdebuginfo={}", debuginfo_level)); } - if env::var_os("RUSTC_EXTERNAL_TOOL").is_none() { - if use_internal_lints(crate_name) { - cmd.arg("-Zunstable-options"); - cmd.arg("-Wrustc::internal"); - } - } - if let Some(target) = target { // The stage0 compiler has a special sysroot distinct from what we // actually downloaded, so we just always pass the `--sysroot` option, @@ -261,14 +254,6 @@ fn main() { std::process::exit(code); } -// Rustc crates for which internal lints are in effect. -fn use_internal_lints(crate_name: Option<&str>) -> bool { - crate_name.map_or(false, |crate_name| { - crate_name.starts_with("rustc") || crate_name.starts_with("syntax") || - ["arena", "fmt_macros"].contains(&crate_name) - }) -} - #[cfg(unix)] fn exec_cmd(cmd: &mut Command) -> io::Result { use std::os::unix::process::CommandExt; diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index e415389d307e7..62b77af13c1e9 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1067,6 +1067,14 @@ impl<'a> Builder<'a> { } } + match mode { + Mode::Rustc | Mode::Codegen => { + rustflags.arg("-Zunstable-options"); + rustflags.arg("-Wrustc::internal"); + } + _ => {} + } + // Throughout the build Cargo can execute a number of build scripts // compiling C/C++ code and we need to pass compilers, archivers, flags, etc // obtained previously to those build scripts. diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 67a48ca4af902..e45d56c320cd8 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -15,6 +15,7 @@ Core encoding and decoding interfaces. #![feature(nll)] #![feature(associated_type_bounds)] #![cfg_attr(test, feature(test))] +#![allow(rustc::internal)] pub use self::serialize::{Decoder, Encoder, Decodable, Encodable}; From 2d6f3fede071514724e280a4394d915616b42634 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 9 Sep 2019 09:42:56 -0700 Subject: [PATCH 107/413] Move handling of `codegen-units` to `builder.rs` --- src/bootstrap/bin/rustc.rs | 4 ---- src/bootstrap/builder.rs | 14 ++++++++++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 62ab6ef7ebe33..84bb539036029 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -165,10 +165,6 @@ fn main() { cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions)); } - if let Ok(s) = env::var("RUSTC_CODEGEN_UNITS") { - cmd.arg("-C").arg(format!("codegen-units={}", s)); - } - if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") { cmd.arg("--remap-path-prefix").arg(&map); } diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 62b77af13c1e9..776d163963a59 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -774,7 +774,17 @@ impl<'a> Builder<'a> { cargo .env("CARGO_TARGET_DIR", out_dir) - .arg(cmd); + .arg(cmd) + .arg("-Zconfig-profile"); + + let profile_var = |name: &str| { + let profile = if self.config.rust_optimize { + "RELEASE" + } else { + "DEV" + }; + format!("CARGO_PROFILE_{}_{}", profile, name) + }; // See comment in librustc_llvm/build.rs for why this is necessary, largely llvm-config // needs to not accidentally link to libLLVM in stage0/lib. @@ -1190,7 +1200,7 @@ impl<'a> Builder<'a> { match (mode, self.config.rust_codegen_units_std, self.config.rust_codegen_units) { (Mode::Std, Some(n), _) | (_, _, Some(n)) => { - cargo.env("RUSTC_CODEGEN_UNITS", n.to_string()); + cargo.env(profile_var("CODEGEN_UNITS"), n.to_string()); } _ => { // Don't set anything From 5abc4cd01cc84252824c88eb4d1106e79168b184 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 9 Sep 2019 09:43:22 -0700 Subject: [PATCH 108/413] Remove duplication of `RUSTC_DEBUGINFO_MAP` in rustc.rs --- src/bootstrap/bin/rustc.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 84bb539036029..32b07c4e993ab 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -164,10 +164,6 @@ fn main() { } else { cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions)); } - - if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") { - cmd.arg("--remap-path-prefix").arg(&map); - } } else { // Override linker if necessary. if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") { From 5cc6eb40827c5a03c378766770c1320ac73d13ed Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 9 Sep 2019 09:49:48 -0700 Subject: [PATCH 109/413] Move debuginfo level handling to `builder.rs` --- src/bootstrap/bin/rustc.rs | 4 ---- src/bootstrap/builder.rs | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 32b07c4e993ab..df7ed48c1867d 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -97,10 +97,6 @@ fn main() { cmd.env("RUST_BACKTRACE", "1"); } - if let Ok(debuginfo_level) = env::var("RUSTC_DEBUGINFO_LEVEL") { - cmd.arg(format!("-Cdebuginfo={}", debuginfo_level)); - } - if let Some(target) = target { // The stage0 compiler has a special sysroot distinct from what we // actually downloaded, so we just always pass the `--sysroot` option, diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 776d163963a59..dd26da7907e75 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -995,7 +995,7 @@ impl<'a> Builder<'a> { Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolRustc => self.config.rust_debuginfo_level_tools, }; - cargo.env("RUSTC_DEBUGINFO_LEVEL", debuginfo_level.to_string()); + cargo.env(profile_var("DEBUG"), debuginfo_level.to_string()); if !mode.is_tool() { cargo.env("RUSTC_FORCE_UNSTABLE", "1"); From 0b6766d8d7461a1a8d632ff62ba2024be87fed76 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 9 Sep 2019 10:17:38 -0700 Subject: [PATCH 110/413] Allow adding `RUSTFLAGS` after `Builder::cargo` This commit changes the return type of `Builder::cargo` to return a builder that allows dynamically adding more `RUSTFLAGS` values after-the-fact. While not used yet, this will later be used to delete more of `rustc.rs` --- src/bootstrap/builder.rs | 49 +++++++++++++++++++++++++++++++++++----- src/bootstrap/check.rs | 24 ++++++++++---------- src/bootstrap/compile.rs | 25 ++++++++++---------- src/bootstrap/doc.rs | 6 ++--- src/bootstrap/test.rs | 38 +++++++++++++++---------------- src/bootstrap/tool.rs | 12 +++++----- 6 files changed, 95 insertions(+), 59 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index dd26da7907e75..a039f7b8c85e6 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -3,6 +3,7 @@ use std::cell::{Cell, RefCell}; use std::collections::BTreeSet; use std::collections::HashMap; use std::env; +use std::ffi::OsStr; use std::fmt::Debug; use std::fs; use std::hash::Hash; @@ -682,7 +683,7 @@ impl<'a> Builder<'a> { /// Adds the compiler's directory of dynamic libraries to `cmd`'s dynamic /// library lookup path. - pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Command) { + pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Cargo) { // Windows doesn't need dylib path munging because the dlls for the // compiler live next to the compiler and the system will find them // automatically. @@ -690,7 +691,7 @@ impl<'a> Builder<'a> { return; } - add_lib_path(vec![self.rustc_libdir(compiler)], cmd); + add_lib_path(vec![self.rustc_libdir(compiler)], &mut cmd.command); } /// Gets a path to the compiler specified. @@ -752,7 +753,7 @@ impl<'a> Builder<'a> { mode: Mode, target: Interned, cmd: &str, - ) -> Command { + ) -> Cargo { let mut cargo = Command::new(&self.initial_cargo); let out_dir = self.stage_out(compiler, mode); @@ -1225,9 +1226,10 @@ impl<'a> Builder<'a> { self.ci_env.force_coloring_in_ci(&mut cargo); - cargo.env("RUSTFLAGS", &rustflags.0); - - cargo + Cargo { + command: cargo, + rustflags, + } } /// Ensure that a given step is built, returning its output. This will @@ -1328,6 +1330,7 @@ impl<'a> Builder<'a> { #[cfg(test)] mod tests; +#[derive(Debug)] struct Rustflags(String); impl Rustflags { @@ -1364,3 +1367,37 @@ impl Rustflags { self } } + +#[derive(Debug)] +pub struct Cargo { + command: Command, + rustflags: Rustflags, +} + +impl Cargo { + pub fn arg(&mut self, arg: impl AsRef) -> &mut Cargo { + self.command.arg(arg.as_ref()); + self + } + + pub fn args(&mut self, args: I) -> &mut Cargo + where I: IntoIterator, S: AsRef + { + for arg in args { + self.arg(arg.as_ref()); + } + self + } + + pub fn env(&mut self, key: impl AsRef, value: impl AsRef) -> &mut Cargo { + self.command.env(key.as_ref(), value.as_ref()); + self + } +} + +impl From for Command { + fn from(mut cargo: Cargo) -> Command { + cargo.command.env("RUSTFLAGS", &cargo.rustflags.0); + cargo.command + } +} diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 205a80c3a3a9e..cadb9a7e441f2 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -52,7 +52,7 @@ impl Step for Std { builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, - &mut cargo, + cargo, args(builder.kind), &libstd_stamp(builder, compiler, target), true); @@ -100,7 +100,7 @@ impl Step for Rustc { builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, - &mut cargo, + cargo, args(builder.kind), &librustc_stamp(builder, compiler, target), true); @@ -152,7 +152,7 @@ impl Step for CodegenBackend { // We won't build LLVM if it's not available, as it shouldn't affect `check`. run_cargo(builder, - &mut cargo, + cargo, args(builder.kind), &codegen_backend_stamp(builder, compiler, target, backend), true); @@ -185,18 +185,18 @@ impl Step for Rustdoc { builder.ensure(Rustc { target }); - let mut cargo = prepare_tool_cargo(builder, - compiler, - Mode::ToolRustc, - target, - cargo_subcommand(builder.kind), - "src/tools/rustdoc", - SourceType::InTree, - &[]); + let cargo = prepare_tool_cargo(builder, + compiler, + Mode::ToolRustc, + target, + cargo_subcommand(builder.kind), + "src/tools/rustdoc", + SourceType::InTree, + &[]); println!("Checking rustdoc artifacts ({} -> {})", &compiler.host, target); run_cargo(builder, - &mut cargo, + cargo, args(builder.kind), &rustdoc_stamp(builder, compiler, target), true); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 9a964457ef285..c63856b6f6e26 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -21,6 +21,7 @@ use serde::Deserialize; use serde_json; use crate::dist; +use crate::builder::Cargo; use crate::util::{exe, is_dylib}; use crate::{Compiler, Mode, GitRepo}; use crate::native; @@ -98,7 +99,7 @@ impl Step for Std { builder.info(&format!("Building stage{} std artifacts ({} -> {})", compiler.stage, &compiler.host, target)); run_cargo(builder, - &mut cargo, + cargo, vec![], &libstd_stamp(builder, compiler, target), false); @@ -156,7 +157,7 @@ fn copy_third_party_objects(builder: &Builder<'_>, compiler: &Compiler, target: pub fn std_cargo(builder: &Builder<'_>, compiler: &Compiler, target: Interned, - cargo: &mut Command) { + cargo: &mut Cargo) { if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } @@ -430,7 +431,7 @@ impl Step for Rustc { builder.info(&format!("Building stage{} compiler artifacts ({} -> {})", compiler.stage, &compiler.host, target)); run_cargo(builder, - &mut cargo, + cargo, vec![], &librustc_stamp(builder, compiler, target), false); @@ -443,14 +444,14 @@ impl Step for Rustc { } } -pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Command) { +pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Cargo) { cargo.arg("--features").arg(builder.rustc_features()) .arg("--manifest-path") .arg(builder.src.join("src/rustc/Cargo.toml")); rustc_cargo_env(builder, cargo); } -pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Command) { +pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo) { // Set some configuration variables picked up by build scripts and // the compiler alike cargo.env("CFG_RELEASE", builder.rust_release()) @@ -577,14 +578,11 @@ impl Step for CodegenBackend { rustc_cargo_env(builder, &mut cargo); let features = build_codegen_backend(&builder, &mut cargo, &compiler, target, backend); + cargo.arg("--features").arg(features); let tmp_stamp = out_dir.join(".tmp.stamp"); - let files = run_cargo(builder, - cargo.arg("--features").arg(features), - vec![], - &tmp_stamp, - false); + let files = run_cargo(builder, cargo, vec![], &tmp_stamp, false); if builder.config.dry_run { return; } @@ -609,7 +607,7 @@ impl Step for CodegenBackend { } pub fn build_codegen_backend(builder: &Builder<'_>, - cargo: &mut Command, + cargo: &mut Cargo, compiler: &Compiler, target: Interned, backend: Interned) -> String { @@ -949,7 +947,7 @@ pub fn add_to_sysroot( } pub fn run_cargo(builder: &Builder<'_>, - cargo: &mut Command, + cargo: Cargo, tail_args: Vec, stamp: &Path, is_check: bool) @@ -1081,10 +1079,11 @@ pub fn run_cargo(builder: &Builder<'_>, pub fn stream_cargo( builder: &Builder<'_>, - cargo: &mut Command, + cargo: Cargo, tail_args: Vec, cb: &mut dyn FnMut(CargoMessage<'_>), ) -> bool { + let mut cargo = Command::from(cargo); if builder.config.dry_run { return true; } diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 873a3c31d1535..4ee8cd2485c02 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -475,7 +475,7 @@ impl Step for Std { .arg("--resource-suffix").arg(crate::channel::CFG_RELEASE_NUM) .arg("--index-page").arg(&builder.src.join("src/doc/index.md")); - builder.run(&mut cargo); + builder.run(&mut cargo.into()); }; for krate in &["alloc", "core", "std", "proc_macro", "test"] { run_cargo_rustdoc_for(krate); @@ -561,7 +561,7 @@ impl Step for Rustc { cargo.arg("-p").arg(krate); } - builder.run(&mut cargo); + builder.run(&mut cargo.into()); } } @@ -656,7 +656,7 @@ impl Step for Rustdoc { cargo.arg("-p").arg("rustdoc"); cargo.env("RUSTDOCFLAGS", "--document-private-items"); - builder.run(&mut cargo); + builder.run(&mut cargo.into()); } } diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 37718ed89c17f..90d1d9d6b7cef 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -233,10 +233,9 @@ impl Step for Cargo { // those features won't be able to land. cargo.env("CARGO_TEST_DISABLE_NIGHTLY", "1"); - try_run( - builder, - cargo.env("PATH", &path_for_cargo(builder, compiler)), - ); + cargo.env("PATH", &path_for_cargo(builder, compiler)); + + try_run(builder, &mut cargo.into()); } } @@ -290,7 +289,7 @@ impl Step for Rls { cargo.arg("--") .args(builder.config.cmd.test_args()); - if try_run(builder, &mut cargo) { + if try_run(builder, &mut cargo.into()) { builder.save_toolstate("rls", ToolState::TestPass); } } @@ -348,7 +347,7 @@ impl Step for Rustfmt { builder.add_rustc_lib_path(compiler, &mut cargo); - if try_run(builder, &mut cargo) { + if try_run(builder, &mut cargo.into()) { builder.save_toolstate("rustfmt", ToolState::TestPass); } } @@ -418,6 +417,7 @@ impl Step for Miri { cargo.env("CARGO_INSTALL_ROOT", &builder.out); // cargo adds a `bin/` cargo.env("XARGO", builder.out.join("bin").join("xargo")); + let mut cargo = Command::from(cargo); if !try_run(builder, &mut cargo) { return; } @@ -467,7 +467,7 @@ impl Step for Miri { builder.add_rustc_lib_path(compiler, &mut cargo); - if !try_run(builder, &mut cargo) { + if !try_run(builder, &mut cargo.into()) { return; } @@ -502,16 +502,16 @@ impl Step for CompiletestTest { let host = self.host; let compiler = builder.compiler(0, host); - let mut cargo = tool::prepare_tool_cargo(builder, - compiler, - Mode::ToolBootstrap, - host, - "test", - "src/tools/compiletest", - SourceType::InTree, - &[]); + let cargo = tool::prepare_tool_cargo(builder, + compiler, + Mode::ToolBootstrap, + host, + "test", + "src/tools/compiletest", + SourceType::InTree, + &[]); - try_run(builder, &mut cargo); + try_run(builder, &mut cargo.into()); } } @@ -571,7 +571,7 @@ impl Step for Clippy { builder.add_rustc_lib_path(compiler, &mut cargo); - if try_run(builder, &mut cargo) { + if try_run(builder, &mut cargo.into()) { builder.save_toolstate("clippy-driver", ToolState::TestPass); } } else { @@ -1841,7 +1841,7 @@ impl Step for Crate { test_kind, krate, compiler.stage, &compiler.host, target )); let _time = util::timeit(&builder); - try_run(builder, &mut cargo); + try_run(builder, &mut cargo.into()); } } @@ -1909,7 +1909,7 @@ impl Step for CrateRustdoc { )); let _time = util::timeit(&builder); - try_run(builder, &mut cargo); + try_run(builder, &mut cargo.into()); } } diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 54fe26f18e741..553adb0ebb64c 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -8,7 +8,7 @@ use build_helper::t; use crate::Mode; use crate::Compiler; -use crate::builder::{Step, RunConfig, ShouldRun, Builder}; +use crate::builder::{Step, RunConfig, ShouldRun, Builder, Cargo as CargoCommand}; use crate::util::{exe, add_lib_path, CiEnv}; use crate::compile; use crate::channel::GitInfo; @@ -63,7 +63,7 @@ impl Step for ToolBuild { _ => panic!("unexpected Mode for tool build") } - let mut cargo = prepare_tool_cargo( + let cargo = prepare_tool_cargo( builder, compiler, self.mode, @@ -76,7 +76,7 @@ impl Step for ToolBuild { builder.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target)); let mut duplicates = Vec::new(); - let is_expected = compile::stream_cargo(builder, &mut cargo, vec![], &mut |msg| { + let is_expected = compile::stream_cargo(builder, cargo, vec![], &mut |msg| { // Only care about big things like the RLS/Cargo for now match tool { | "rls" @@ -229,7 +229,7 @@ pub fn prepare_tool_cargo( path: &'static str, source_type: SourceType, extra_features: &[String], -) -> Command { +) -> CargoCommand { let mut cargo = builder.cargo(compiler, mode, target, command); let dir = builder.src.join(path); cargo.arg("--manifest-path").arg(dir.join("Cargo.toml")); @@ -517,7 +517,7 @@ impl Step for Rustdoc { // libraries here. The intuition here is that If we've built a compiler, we should be able // to build rustdoc. - let mut cargo = prepare_tool_cargo( + let cargo = prepare_tool_cargo( builder, build_compiler, Mode::ToolRustc, @@ -530,7 +530,7 @@ impl Step for Rustdoc { builder.info(&format!("Building rustdoc for stage{} ({})", target_compiler.stage, target_compiler.host)); - builder.run(&mut cargo); + builder.run(&mut cargo.into()); // Cargo adds a number of paths to the dylib search path on windows, which results in // the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool" From 3d13f463045417903364c44a67b0963ececde79f Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 9 Sep 2019 10:21:15 -0700 Subject: [PATCH 111/413] Move handling of `{MUSL,WASI}_ROOT` to `compile.rs` No longer any need for them to live in `rustc.rs`! --- src/bootstrap/bin/rustc.rs | 20 +------------------- src/bootstrap/builder.rs | 5 +++++ src/bootstrap/compile.rs | 8 ++++++-- 3 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index df7ed48c1867d..8c460c59f07eb 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -16,7 +16,6 @@ //! never get replaced. use std::env; -use std::ffi::OsString; use std::io; use std::path::PathBuf; use std::process::Command; @@ -97,7 +96,7 @@ fn main() { cmd.env("RUST_BACKTRACE", "1"); } - if let Some(target) = target { + if target.is_some() { // The stage0 compiler has a special sysroot distinct from what we // actually downloaded, so we just always pass the `--sysroot` option, // unless one is already set. @@ -112,23 +111,6 @@ fn main() { cmd.arg("-Cprefer-dynamic"); } - // Help the libc crate compile by assisting it in finding various - // sysroot native libraries. - if let Some(s) = env::var_os("MUSL_ROOT") { - if target.contains("musl") { - let mut root = OsString::from("native="); - root.push(&s); - root.push("/lib"); - cmd.arg("-L").arg(&root); - } - } - if let Some(s) = env::var_os("WASI_ROOT") { - let mut root = OsString::from("native="); - root.push(&s); - root.push("/lib/wasm32-wasi"); - cmd.arg("-L").arg(&root); - } - // If we're compiling specifically the `panic_abort` crate then we pass // the `-C panic=abort` option. Note that we do not do this for any // other crate intentionally as this is the only crate for now that we diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index a039f7b8c85e6..6a483c1fafd91 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1375,6 +1375,11 @@ pub struct Cargo { } impl Cargo { + pub fn rustflag(&mut self, arg: &str) -> &mut Cargo { + self.rustflags.arg(arg); + self + } + pub fn arg(&mut self, arg: impl AsRef) -> &mut Cargo { self.command.arg(arg.as_ref()); self diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index c63856b6f6e26..dc0961d16e85d 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -220,15 +220,19 @@ pub fn std_cargo(builder: &Builder<'_>, .arg("--manifest-path") .arg(builder.src.join("src/libtest/Cargo.toml")); + // Help the libc crate compile by assisting it in finding various + // sysroot native libraries. if target.contains("musl") { if let Some(p) = builder.musl_root(target) { - cargo.env("MUSL_ROOT", p); + let root = format!("native={}/lib", p.to_str().unwrap()); + cargo.rustflag("-L").rustflag(&root); } } if target.ends_with("-wasi") { if let Some(p) = builder.wasi_root(target) { - cargo.env("WASI_ROOT", p); + let root = format!("native={}/lib/wasm32-wasi", p.to_str().unwrap()); + cargo.rustflag("-L").rustflag(&root); } } } From a816fa185b42bc1bd73cd241be27121dcc5b784b Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 9 Sep 2019 10:22:24 -0700 Subject: [PATCH 112/413] Move handling of `RUSTC_PARALLEL_COMPILER` to `compile.rs` No longer needs to live in `rustc.rs` --- src/bootstrap/bin/rustc.rs | 4 ---- src/bootstrap/compile.rs | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 8c460c59f07eb..b71119cc57ced 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -170,10 +170,6 @@ fn main() { cmd.arg("-Z").arg("force-unstable-if-unmarked"); } - if env::var_os("RUSTC_PARALLEL_COMPILER").is_some() { - cmd.arg("--cfg").arg("parallel_compiler"); - } - if verbose > 1 { eprintln!( "rustc command: {:?}={:?} {:?}", diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index dc0961d16e85d..6ea32edfb208b 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -480,7 +480,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo) { cargo.env("CFG_DEFAULT_LINKER", s); } if builder.config.rustc_parallel { - cargo.env("RUSTC_PARALLEL_COMPILER", "1"); + cargo.rustflag("--cfg=parallel_compiler"); } if builder.config.rust_verify_llvm_ir { cargo.env("RUSTC_VERIFY_LLVM_IR", "1"); From b3f95f460f6c35985bf7b3e6220b1370e0323312 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 9 Sep 2019 10:27:01 -0700 Subject: [PATCH 113/413] Move `--cfg bootstrap` out of `rustc.rs` Instead let's do this via `RUSTFLAGS` in `builder.rs`. Currently requires a submodule update of `stdarch` to fix a problem with previous compilers. --- src/bootstrap/bin/rustc.rs | 15 --------------- src/bootstrap/builder.rs | 1 + src/libcore/bool.rs | 2 +- src/libcore/clone.rs | 2 +- src/libcore/cmp.rs | 8 ++++---- src/libcore/default.rs | 2 +- src/libcore/fmt/mod.rs | 6 +++--- src/libcore/hash/mod.rs | 2 +- src/libcore/intrinsics.rs | 12 ++++++------ src/libcore/lib.rs | 2 +- src/libcore/macros.rs | 4 ++-- src/libcore/marker.rs | 2 +- src/libcore/num/mod.rs | 24 ++++++++++++------------ src/stdarch | 2 +- 14 files changed, 35 insertions(+), 49 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index b71119cc57ced..528e7787610be 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -76,21 +76,6 @@ fn main() { } } - // Non-zero stages must all be treated uniformly to avoid problems when attempting to uplift - // compiler libraries and such from stage 1 to 2. - // - // FIXME: the fact that core here is excluded is due to core_arch from our stdarch submodule - // being broken on the beta compiler with bootstrap passed, so this is a temporary workaround - // (we've just snapped, so there are no cfg(bootstrap) related annotations in core). - if stage == "0" { - if crate_name != Some("core") { - cmd.arg("--cfg").arg("bootstrap"); - } else { - // NOTE(eddyb) see FIXME above, except now we need annotations again in core. - cmd.arg("--cfg").arg("boostrap_stdarch_ignore_this"); - } - } - // Print backtrace in case of ICE if env::var("RUSTC_BACKTRACE_ON_ICE").is_ok() && env::var("RUST_BACKTRACE").is_err() { cmd.env("RUST_BACKTRACE", "1"); diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 6a483c1fafd91..076947f878161 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -820,6 +820,7 @@ impl<'a> Builder<'a> { rustflags.env("RUSTFLAGS_NOT_BOOTSTRAP"); } else { rustflags.env("RUSTFLAGS_BOOTSTRAP"); + rustflags.arg("--cfg=bootstrap"); } match mode { diff --git a/src/libcore/bool.rs b/src/libcore/bool.rs index 32ec26975e375..f751ccb428030 100644 --- a/src/libcore/bool.rs +++ b/src/libcore/bool.rs @@ -1,6 +1,6 @@ //! impl bool {} -#[cfg(not(boostrap_stdarch_ignore_this))] +#[cfg(not(bootstrap))] #[lang = "bool"] impl bool { /// Returns `Some(t)` if the `bool` is `true`, or `None` otherwise. diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index ec70d396e966d..6bdae1b557d61 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -135,7 +135,7 @@ pub trait Clone : Sized { /// Derive macro generating an impl of the trait `Clone`. #[rustc_builtin_macro] -#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] +#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_clone_copy)] pub macro Clone($item:item) { /* compiler built-in */ } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 4e2b1627e15ef..fc7329f57d45e 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -210,7 +210,7 @@ pub trait PartialEq { /// Derive macro generating an impl of the trait `PartialEq`. #[rustc_builtin_macro] -#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] +#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro PartialEq($item:item) { /* compiler built-in */ } @@ -273,7 +273,7 @@ pub trait Eq: PartialEq { /// Derive macro generating an impl of the trait `Eq`. #[rustc_builtin_macro] -#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] +#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_eq)] pub macro Eq($item:item) { /* compiler built-in */ } @@ -624,7 +624,7 @@ pub trait Ord: Eq + PartialOrd { /// Derive macro generating an impl of the trait `Ord`. #[rustc_builtin_macro] -#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] +#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Ord($item:item) { /* compiler built-in */ } @@ -873,7 +873,7 @@ pub trait PartialOrd: PartialEq { /// Derive macro generating an impl of the trait `PartialOrd`. #[rustc_builtin_macro] -#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] +#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro PartialOrd($item:item) { /* compiler built-in */ } diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 66acc5165fc5b..806d478310760 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -117,7 +117,7 @@ pub trait Default: Sized { /// Derive macro generating an impl of the trait `Default`. #[rustc_builtin_macro] -#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] +#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Default($item:item) { /* compiler built-in */ } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 7e35188bc1082..65e2f8b9be63f 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -518,8 +518,8 @@ impl Display for Arguments<'_> { label="`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`", )] #[doc(alias = "{:?}")] -#[cfg_attr(boostrap_stdarch_ignore_this, lang = "debug_trait")] -#[cfg_attr(not(boostrap_stdarch_ignore_this), rustc_diagnostic_item = "debug_trait")] +#[cfg_attr(bootstrap, lang = "debug_trait")] +#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "debug_trait")] pub trait Debug { /// Formats the value using the given formatter. /// @@ -550,7 +550,7 @@ pub trait Debug { pub(crate) mod macros { /// Derive macro generating an impl of the trait `Debug`. #[rustc_builtin_macro] - #[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] + #[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Debug($item:item) { /* compiler built-in */ } diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index bf3daa32840d8..aaaa6f9c575fd 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -202,7 +202,7 @@ pub trait Hash { pub(crate) mod macros { /// Derive macro generating an impl of the trait `Hash`. #[rustc_builtin_macro] - #[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] + #[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Hash($item:item) { /* compiler built-in */ } diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index ecff40a75978d..905375eb60fe4 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1299,38 +1299,38 @@ extern "rust-intrinsic" { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_add` method. For example, /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add) - #[cfg(boostrap_stdarch_ignore_this)] + #[cfg(bootstrap)] pub fn overflowing_add(a: T, b: T) -> T; /// Returns (a - b) mod 2N, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_sub` method. For example, /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub) - #[cfg(boostrap_stdarch_ignore_this)] + #[cfg(bootstrap)] pub fn overflowing_sub(a: T, b: T) -> T; /// Returns (a * b) mod 2N, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_mul` method. For example, /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul) - #[cfg(boostrap_stdarch_ignore_this)] + #[cfg(bootstrap)] pub fn overflowing_mul(a: T, b: T) -> T; /// Returns (a + b) mod 2N, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_add` method. For example, /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add) - #[cfg(not(boostrap_stdarch_ignore_this))] + #[cfg(not(bootstrap))] pub fn wrapping_add(a: T, b: T) -> T; /// Returns (a - b) mod 2N, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_sub` method. For example, /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub) - #[cfg(not(boostrap_stdarch_ignore_this))] + #[cfg(not(bootstrap))] pub fn wrapping_sub(a: T, b: T) -> T; /// Returns (a * b) mod 2N, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_mul` method. For example, /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul) - #[cfg(not(boostrap_stdarch_ignore_this))] + #[cfg(not(bootstrap))] pub fn wrapping_mul(a: T, b: T) -> T; /// Computes `a + b`, while saturating at numeric bounds. diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index a2cc585fc51fd..5c681b3a5d807 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -87,7 +87,7 @@ #![feature(link_llvm_intrinsics)] #![feature(never_type)] #![feature(nll)] -#![cfg_attr(boostrap_stdarch_ignore_this, feature(bind_by_move_pattern_guards))] +#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![feature(exhaustive_patterns)] #![feature(no_core)] #![feature(on_unimplemented)] diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 384bc87499887..c6f5fb0b16350 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -1236,9 +1236,9 @@ pub(crate) mod builtin { pub macro test($item:item) { /* compiler built-in */ } /// Attribute macro applied to a function to turn it into a benchmark test. - #[cfg_attr(not(boostrap_stdarch_ignore_this), unstable(soft, feature = "test", issue = "50297", + #[cfg_attr(not(bootstrap), unstable(soft, feature = "test", issue = "50297", reason = "`bench` is a part of custom test frameworks which are unstable"))] - #[cfg_attr(boostrap_stdarch_ignore_this, unstable(feature = "test", issue = "50297", + #[cfg_attr(bootstrap, unstable(feature = "test", issue = "50297", reason = "`bench` is a part of custom test frameworks which are unstable"))] #[allow_internal_unstable(test, rustc_attrs)] #[rustc_builtin_macro] diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 347e7dce6e67d..a2cfb320e7698 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -290,7 +290,7 @@ pub trait Copy : Clone { /// Derive macro generating an impl of the trait `Copy`. #[rustc_builtin_macro] -#[cfg_attr(boostrap_stdarch_ignore_this, rustc_macro_transparency = "semitransparent")] +#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_clone_copy)] pub macro Copy($item:item) { /* compiler built-in */ } diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 0cf2ebb487ddd..5d99c10e73815 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1112,11 +1112,11 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_add(self, rhs: Self) -> Self { - #[cfg(boostrap_stdarch_ignore_this)] { + #[cfg(bootstrap)] { intrinsics::overflowing_add(self, rhs) } - #[cfg(not(boostrap_stdarch_ignore_this))] { + #[cfg(not(bootstrap))] { intrinsics::wrapping_add(self, rhs) } } @@ -1141,11 +1141,11 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_sub(self, rhs: Self) -> Self { - #[cfg(boostrap_stdarch_ignore_this)] { + #[cfg(bootstrap)] { intrinsics::overflowing_sub(self, rhs) } - #[cfg(not(boostrap_stdarch_ignore_this))] { + #[cfg(not(bootstrap))] { intrinsics::wrapping_sub(self, rhs) } } @@ -1169,11 +1169,11 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_mul(self, rhs: Self) -> Self { - #[cfg(boostrap_stdarch_ignore_this)] { + #[cfg(bootstrap)] { intrinsics::overflowing_mul(self, rhs) } - #[cfg(not(boostrap_stdarch_ignore_this))] { + #[cfg(not(bootstrap))] { intrinsics::wrapping_mul(self, rhs) } } @@ -3040,11 +3040,11 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_add(self, rhs: Self) -> Self { - #[cfg(boostrap_stdarch_ignore_this)] { + #[cfg(bootstrap)] { intrinsics::overflowing_add(self, rhs) } - #[cfg(not(boostrap_stdarch_ignore_this))] { + #[cfg(not(bootstrap))] { intrinsics::wrapping_add(self, rhs) } } @@ -3068,11 +3068,11 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_sub(self, rhs: Self) -> Self { - #[cfg(boostrap_stdarch_ignore_this)] { + #[cfg(bootstrap)] { intrinsics::overflowing_sub(self, rhs) } - #[cfg(not(boostrap_stdarch_ignore_this))] { + #[cfg(not(bootstrap))] { intrinsics::wrapping_sub(self, rhs) } } @@ -3097,11 +3097,11 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_mul(self, rhs: Self) -> Self { - #[cfg(boostrap_stdarch_ignore_this)] { + #[cfg(bootstrap)] { intrinsics::overflowing_mul(self, rhs) } - #[cfg(not(boostrap_stdarch_ignore_this))] { + #[cfg(not(bootstrap))] { intrinsics::wrapping_mul(self, rhs) } } diff --git a/src/stdarch b/src/stdarch index 4791ba85e7645..e0ab2c165ace0 160000 --- a/src/stdarch +++ b/src/stdarch @@ -1 +1 @@ -Subproject commit 4791ba85e7645c02146dd416288480943670d1ca +Subproject commit e0ab2c165ace03a61139b61f1d9b86b07028850f From 385470b8bb1250ac11276fa57a3d1fc1d9ffb710 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 9 Sep 2019 10:31:22 -0700 Subject: [PATCH 114/413] Move handling of `-Cprefer-dynamic` into `builder.rs` This logic is *super* old and can be tweaked and moved into `builder.rs` --- src/bootstrap/bin/rustc.rs | 7 ------- src/bootstrap/builder.rs | 10 ++++++++++ src/bootstrap/test.rs | 4 ---- src/bootstrap/tool.rs | 4 ---- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 528e7787610be..0abfa023addef 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -89,13 +89,6 @@ fn main() { cmd.arg("--sysroot").arg(&sysroot); } - // When we build Rust dylibs they're all intended for intermediate - // usage, so make sure we pass the -Cprefer-dynamic flag instead of - // linking all deps statically into the dylib. - if env::var_os("RUSTC_NO_PREFER_DYNAMIC").is_none() { - cmd.arg("-Cprefer-dynamic"); - } - // If we're compiling specifically the `panic_abort` crate then we pass // the `-C panic=abort` option. Note that we do not do this for any // other crate intentionally as this is the only crate for now that we diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 076947f878161..428926e106b08 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1227,6 +1227,16 @@ impl<'a> Builder<'a> { self.ci_env.force_coloring_in_ci(&mut cargo); + // When we build Rust dylibs they're all intended for intermediate + // usage, so make sure we pass the -Cprefer-dynamic flag instead of + // linking all deps statically into the dylib. + match mode { + Mode::Std | Mode::Rustc | Mode::Codegen => { + rustflags.arg("-Cprefer-dynamic"); + } + _ => {} + } + Cargo { command: cargo, rustflags, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 90d1d9d6b7cef..b7ce9c7b39709 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1814,10 +1814,6 @@ impl Step for Crate { .expect("nodejs not configured"), ); } else if target.starts_with("wasm32") { - // On the wasm32-unknown-unknown target we're using LTO which is - // incompatible with `-C prefer-dynamic`, so disable that here - cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); - let node = builder .config .nodejs diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 553adb0ebb64c..f1baeafe26afb 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -234,10 +234,6 @@ pub fn prepare_tool_cargo( let dir = builder.src.join(path); cargo.arg("--manifest-path").arg(dir.join("Cargo.toml")); - // We don't want to build tools dynamically as they'll be running across - // stages and such and it's just easier if they're not dynamically linked. - cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1"); - if source_type == SourceType::Submodule { cargo.env("RUSTC_EXTERNAL_TOOL", "1"); } From 160787129b757f364ce9ef44510845ec0c1c4410 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 9 Sep 2019 10:34:31 -0700 Subject: [PATCH 115/413] Add some FIXME for future Cargo issues --- src/bootstrap/bin/rustc.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 0abfa023addef..475f2e904639c 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -115,12 +115,18 @@ fn main() { // The compiler builtins are pretty sensitive to symbols referenced in // libcore and such, so we never compile them with debug assertions. + // + // FIXME(rust-lang/cargo#7253) we should be doing this in `builder.rs` + // with env vars instead of doing it here in this script. if crate_name == Some("compiler_builtins") { cmd.arg("-C").arg("debug-assertions=no"); } else { cmd.arg("-C").arg(format!("debug-assertions={}", debug_assertions)); } } else { + // FIXME(rust-lang/cargo#5754) we shouldn't be using special env vars + // here, but rather Cargo should know what flags to pass rustc itself. + // Override linker if necessary. if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") { cmd.arg(format!("-Clinker={}", host_linker)); From 9b34ef643f82f14b7c94041af4b34788801c9983 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 10 Sep 2019 09:10:24 -0700 Subject: [PATCH 116/413] Stylistic changes --- src/bootstrap/builder.rs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 428926e106b08..9046eded381c6 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1079,12 +1079,9 @@ impl<'a> Builder<'a> { } } - match mode { - Mode::Rustc | Mode::Codegen => { - rustflags.arg("-Zunstable-options"); - rustflags.arg("-Wrustc::internal"); - } - _ => {} + if let Mode::Rustc | Mode::Codegen = mode { + rustflags.arg("-Zunstable-options"); + rustflags.arg("-Wrustc::internal"); } // Throughout the build Cargo can execute a number of build scripts @@ -1230,11 +1227,8 @@ impl<'a> Builder<'a> { // When we build Rust dylibs they're all intended for intermediate // usage, so make sure we pass the -Cprefer-dynamic flag instead of // linking all deps statically into the dylib. - match mode { - Mode::Std | Mode::Rustc | Mode::Codegen => { - rustflags.arg("-Cprefer-dynamic"); - } - _ => {} + if let Mode::Std | Mode::Rustc | Mode::Codegen = mode { + rustflags.arg("-Cprefer-dynamic"); } Cargo { @@ -1348,7 +1342,7 @@ impl Rustflags { fn new(target: &str, cmd: &mut Command) -> Rustflags { let mut ret = Rustflags(String::new()); - // Inherit `RUSTFLAGS` by default + // Inherit `RUSTFLAGS` by default ... ret.env("RUSTFLAGS"); // ... and also handle target-specific env RUSTFLAGS if they're @@ -1358,7 +1352,7 @@ impl Rustflags { ret.env(&target_specific); cmd.env_remove(&target_specific); - return ret; + ret } fn env(&mut self, env: &str) { From 7b907ded0e38f0bba7b7fee43b4a7f4669564ae8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 10 Sep 2019 09:10:32 -0700 Subject: [PATCH 117/413] Fix compiling libserialize tests They've got new warnings turned on so they need more `#![allow]` --- src/libserialize/tests/json.rs | 2 ++ src/libserialize/tests/opaque.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/libserialize/tests/json.rs b/src/libserialize/tests/json.rs index 3fb6bda679bc1..8342e4f97426e 100644 --- a/src/libserialize/tests/json.rs +++ b/src/libserialize/tests/json.rs @@ -1,3 +1,5 @@ +#![allow(rustc::default_hash_types)] + extern crate serialize as rustc_serialize; use rustc_serialize::{Encodable, Decodable}; diff --git a/src/libserialize/tests/opaque.rs b/src/libserialize/tests/opaque.rs index fff6fc69e7842..26b113699c68d 100644 --- a/src/libserialize/tests/opaque.rs +++ b/src/libserialize/tests/opaque.rs @@ -1,3 +1,5 @@ +#![allow(rustc::default_hash_types)] + extern crate serialize as rustc_serialize; use rustc_serialize::{Encodable, Decodable}; From 7342325dfbd2560ebfd1b95073a20dfc56bd0298 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 10 Sep 2019 09:28:47 -0700 Subject: [PATCH 118/413] Add `#![deny(warnings)]` to internal tools --- src/tools/build-manifest/src/main.rs | 2 ++ src/tools/cargotest/main.rs | 2 ++ src/tools/compiletest/src/main.rs | 1 + src/tools/error_index_generator/main.rs | 1 + src/tools/linkchecker/main.rs | 2 ++ src/tools/remote-test-client/src/main.rs | 14 ++++++++------ src/tools/remote-test-server/src/main.rs | 24 +++++++++++++----------- src/tools/tidy/src/main.rs | 2 ++ src/tools/unstable-book-gen/src/main.rs | 2 ++ 9 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index eab23f3cfffc4..f41e7dd17ede6 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -4,6 +4,8 @@ //! via `x.py dist hash-and-sign`; the cmdline arguments are set up //! by rustbuild (in `src/bootstrap/dist.rs`). +#![deny(warnings)] + use toml; use serde::Serialize; diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs index f6aaaa5c6eadb..1a42e0cac3ccc 100644 --- a/src/tools/cargotest/main.rs +++ b/src/tools/cargotest/main.rs @@ -1,3 +1,5 @@ +#![deny(warnings)] + use std::env; use std::process::Command; use std::path::{Path, PathBuf}; diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 7c51de5df2267..34435819a2c46 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -1,6 +1,7 @@ #![crate_name = "compiletest"] #![feature(test)] #![feature(vec_remove_item)] +#![deny(warnings)] extern crate test; diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs index c4826a0c31d6c..31a802706cba4 100644 --- a/src/tools/error_index_generator/main.rs +++ b/src/tools/error_index_generator/main.rs @@ -1,4 +1,5 @@ #![feature(rustc_private)] +#![deny(warnings)] extern crate env_logger; extern crate syntax; diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index 49c149afe17f9..e8a7252cb767c 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -14,6 +14,8 @@ //! A few whitelisted exceptions are allowed as there's known bugs in rustdoc, //! but this should catch the majority of "broken link" cases. +#![deny(warnings)] + use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet}; use std::env; diff --git a/src/tools/remote-test-client/src/main.rs b/src/tools/remote-test-client/src/main.rs index a1d52251263d4..d7f031a6150ae 100644 --- a/src/tools/remote-test-client/src/main.rs +++ b/src/tools/remote-test-client/src/main.rs @@ -1,9 +1,11 @@ -/// This is a small client program intended to pair with `remote-test-server` in -/// this repository. This client connects to the server over TCP and is used to -/// push artifacts and run tests on the server instead of locally. -/// -/// Here is also where we bake in the support to spawn the QEMU emulator as -/// well. +//! This is a small client program intended to pair with `remote-test-server` in +//! this repository. This client connects to the server over TCP and is used to +//! push artifacts and run tests on the server instead of locally. +//! +//! Here is also where we bake in the support to spawn the QEMU emulator as +//! well. + +#![deny(warnings)] use std::env; use std::fs::{self, File}; diff --git a/src/tools/remote-test-server/src/main.rs b/src/tools/remote-test-server/src/main.rs index d2238730196aa..0462b719b7be1 100644 --- a/src/tools/remote-test-server/src/main.rs +++ b/src/tools/remote-test-server/src/main.rs @@ -1,14 +1,16 @@ -/// This is a small server which is intended to run inside of an emulator or -/// on a remote test device. This server pairs with the `remote-test-client` -/// program in this repository. The `remote-test-client` connects to this -/// server over a TCP socket and performs work such as: -/// -/// 1. Pushing shared libraries to the server -/// 2. Running tests through the server -/// -/// The server supports running tests concurrently and also supports tests -/// themselves having support libraries. All data over the TCP sockets is in a -/// basically custom format suiting our needs. +//! This is a small server which is intended to run inside of an emulator or +//! on a remote test device. This server pairs with the `remote-test-client` +//! program in this repository. The `remote-test-client` connects to this +//! server over a TCP socket and performs work such as: +//! +//! 1. Pushing shared libraries to the server +//! 2. Running tests through the server +//! +//! The server supports running tests concurrently and also supports tests +//! themselves having support libraries. All data over the TCP sockets is in a +//! basically custom format suiting our needs. + +#![deny(warnings)] use std::cmp; use std::env; diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 5deac52f08b5e..a57238ad8148a 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -4,6 +4,8 @@ //! etc. This is run by default on `make check` and as part of the auto //! builders. +#![deny(warnings)] + use tidy::*; use std::process; diff --git a/src/tools/unstable-book-gen/src/main.rs b/src/tools/unstable-book-gen/src/main.rs index 036349ea1c82a..fdb0b6d3e5653 100644 --- a/src/tools/unstable-book-gen/src/main.rs +++ b/src/tools/unstable-book-gen/src/main.rs @@ -1,5 +1,7 @@ //! Auto-generate stub docs for the unstable book +#![deny(warnings)] + use tidy::features::{Feature, Features, collect_lib_features, collect_lang_features}; use tidy::unstable_book::{collect_unstable_feature_names, collect_unstable_book_section_file_names, PATH_STR, LANG_FEATURES_DIR, LIB_FEATURES_DIR}; From ff6a7c77aecc0e1dcf15491a04c0cb815dec489e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 11 Sep 2019 08:06:25 -0700 Subject: [PATCH 119/413] No need to remove target-specific RUSTFLAGS Turns out Cargo favors RUSTFLAGS! --- src/bootstrap/builder.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 9046eded381c6..aa433690436ee 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -815,7 +815,7 @@ impl<'a> Builder<'a> { stage = compiler.stage; } - let mut rustflags = Rustflags::new(&target, &mut cargo); + let mut rustflags = Rustflags::new(&target); if stage != 0 { rustflags.env("RUSTFLAGS_NOT_BOOTSTRAP"); } else { @@ -1339,18 +1339,16 @@ mod tests; struct Rustflags(String); impl Rustflags { - fn new(target: &str, cmd: &mut Command) -> Rustflags { + fn new(target: &str) -> Rustflags { let mut ret = Rustflags(String::new()); // Inherit `RUSTFLAGS` by default ... ret.env("RUSTFLAGS"); // ... and also handle target-specific env RUSTFLAGS if they're - // configured. If this is configured we also remove it from the - // environment because Cargo will prefer it over RUSTFLAGS. + // configured. let target_specific = format!("CARGO_TARGET_{}_RUSTFLAGS", crate::envify(target)); ret.env(&target_specific); - cmd.env_remove(&target_specific); ret } From d8253c166b4562782b157a0feca43667d6cb05c6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 16 Sep 2019 14:01:11 -0700 Subject: [PATCH 120/413] Tweak libserialize allows --- src/libserialize/tests/json.rs | 2 +- src/libserialize/tests/opaque.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libserialize/tests/json.rs b/src/libserialize/tests/json.rs index 8342e4f97426e..898168252e554 100644 --- a/src/libserialize/tests/json.rs +++ b/src/libserialize/tests/json.rs @@ -1,4 +1,4 @@ -#![allow(rustc::default_hash_types)] +#![allow(rustc::internal)] extern crate serialize as rustc_serialize; diff --git a/src/libserialize/tests/opaque.rs b/src/libserialize/tests/opaque.rs index 26b113699c68d..592bc09039947 100644 --- a/src/libserialize/tests/opaque.rs +++ b/src/libserialize/tests/opaque.rs @@ -1,4 +1,4 @@ -#![allow(rustc::default_hash_types)] +#![allow(rustc::internal)] extern crate serialize as rustc_serialize; From 008ed188ce48bfc555e91212730fc49208611caa Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 17 Sep 2019 11:23:09 -0700 Subject: [PATCH 121/413] rustbuild: Pass `-Zsave-analysis` during tests This is needed to ensure that the crates during a normal build are shared with the crates during testing, otherwise they'll end up hasing differently and we'll recompile crates like `core` during tests. --- src/bootstrap/builder.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index aa433690436ee..5d586f0c461db 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1134,8 +1134,7 @@ impl<'a> Builder<'a> { } } - if (cmd == "build" || cmd == "rustc") - && mode == Mode::Std + if mode == Mode::Std && self.config.extended && compiler.is_final_stage(self) { From b92330691378199f14facf4776c197826b9d0fab Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 18 Sep 2019 12:34:19 -0700 Subject: [PATCH 122/413] Remove `--enable-extended` from cross dist builder Shouldn't have an effect on produced artifacts and otherwise is causing issues where `-Zsave-analysis` is passed during tests but fails compilation. --- Cargo.lock | 1 - src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile | 1 - src/tools/cargo | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fa749e5e3aebe..5bc1938fee260 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -597,7 +597,6 @@ version = "0.28.0" dependencies = [ "curl", "failure", - "http", "percent-encoding 2.0.0", "serde", "serde_derive", diff --git a/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile b/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile index ba2d32a9296b4..61c363fbfd675 100644 --- a/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile +++ b/src/ci/docker/dist-i586-gnu-i586-i686-musl/Dockerfile @@ -32,7 +32,6 @@ RUN sh /scripts/sccache.sh ENV RUST_CONFIGURE_ARGS \ --musl-root-i586=/musl-i586 \ --musl-root-i686=/musl-i686 \ - --enable-extended \ --disable-docs # Newer binutils broke things on some vms/distros (i.e., linking against diff --git a/src/tools/cargo b/src/tools/cargo index 3596cb86b2e87..b6c6f685b38d5 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 3596cb86b2e87dd9b9c1bb90d4a9d73ec2c1512f +Subproject commit b6c6f685b38d523580813b0031677c2298f458ea From 1a8897fd8a988cc3c81b7cb985005d6cf836116c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 23 Sep 2019 09:35:50 -0700 Subject: [PATCH 123/413] Fix rebase conflicts --- src/libcore/panicking.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index 3d2bc24bf24a5..7b7253419b1bd 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -71,7 +71,7 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>, file_line_col: &(&'static str, u32, u3 } // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call - #[cfg_attr(boostrap_stdarch_ignore_this, allow(improper_ctypes))] + #[cfg_attr(bootstrap, allow(improper_ctypes))] extern "Rust" { #[lang = "panic_impl"] fn panic_impl(pi: &PanicInfo<'_>) -> !; From 62fc4d36dfeedbf0795f36a8d08c39e0f4e41632 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 23 Sep 2019 19:29:02 +0200 Subject: [PATCH 124/413] stash_diagnostic: ICE in a different way --- src/librustc_errors/lib.rs | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 40f63ae1eee33..cdaa528e8e497 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -466,10 +466,15 @@ impl Handler { /// Stash a given diagnostic with the given `Span` and `StashKey` as the key for later stealing. /// If the diagnostic with this `(span, key)` already exists, this will result in an ICE. pub fn stash_diagnostic(&self, span: Span, key: StashKey, diag: Diagnostic) { - if let Some(old) = self.inner.borrow_mut().stashed_diagnostics.insert((span, key), diag) { + let mut inner = self.inner.borrow_mut(); + if let Some(mut old_diag) = inner.stashed_diagnostics.insert((span, key), diag) { // We are removing a previously stashed diagnostic which should not happen. - // Create a builder and drop it on the floor to get an ICE. - drop(DiagnosticBuilder::new_diagnostic(self, old)); + old_diag.level = Bug; + old_diag.note(&format!( + "{}:{}: already existing stashed diagnostic with (span = {:?}, key = {:?})", + file!(), line!(), span, key + )); + inner.emit_explicit_bug(&old_diag); } } @@ -676,6 +681,11 @@ impl Handler { self.inner.borrow_mut().abort_if_errors_and_should_abort() } + /// `true` if we haven't taught a diagnostic with this code already. + /// The caller must then teach the user about such a diagnostic. + /// + /// Used to suppress emitting the same error multiple times with extended explanation when + /// calling `-Zteach`. pub fn must_teach(&self, code: &DiagnosticId) -> bool { self.inner.borrow_mut().must_teach(code) } @@ -698,11 +708,6 @@ impl Handler { } impl HandlerInner { - /// `true` if we haven't taught a diagnostic with this code already. - /// The caller must then teach the user about such a diagnostic. - /// - /// Used to suppress emitting the same error multiple times with extended explanation when - /// calling `-Zteach`. fn must_teach(&mut self, code: &DiagnosticId) -> bool { self.taught_diagnostics.insert(code.clone()) } @@ -833,7 +838,11 @@ impl HandlerInner { } fn span_bug>(&mut self, sp: S, msg: &str) -> ! { - self.emit_diagnostic(Diagnostic::new(Bug, msg).set_span(sp)); + self.emit_explicit_bug(Diagnostic::new(Bug, msg).set_span(sp)); + } + + fn emit_explicit_bug(&mut self, diag: &Diagnostic) -> ! { + self.emit_diagnostic(diag); self.abort_if_errors_and_should_abort(); panic!(ExplicitBug); } From 2666ae5caa1b07d0b611995f5d137e86bdaa31bc Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Mon, 23 Sep 2019 21:29:12 +0200 Subject: [PATCH 125/413] Remove whitespace from testname --- ...gn.rs => impl[t]-foreign[local,fundamental[t]]-for-foreign.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/coherence/{impl[t]-foreign[local, fundamental[t]]-for-foreign.rs => impl[t]-foreign[local,fundamental[t]]-for-foreign.rs} (100%) diff --git a/src/test/ui/coherence/impl[t]-foreign[local, fundamental[t]]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[local,fundamental[t]]-for-foreign.rs similarity index 100% rename from src/test/ui/coherence/impl[t]-foreign[local, fundamental[t]]-for-foreign.rs rename to src/test/ui/coherence/impl[t]-foreign[local,fundamental[t]]-for-foreign.rs From 5d531aeaf46451f999aea0f7c9ba08016b9ee3eb Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 16 Sep 2019 13:34:57 -0700 Subject: [PATCH 126/413] rustc: Convert `dependency_formats` to a query This commit converts a field of `Session`, `dependency_formats`, into a query of `TyCtxt`. This information then also needed to be threaded through to other remaining portions of the linker, but it's relatively straightforward. The only change here is that instead of `HashMap` the data structure changed to `Vec<(CrateType, T)>` to make it easier to deal with in queries. --- src/librustc/middle/dependency_format.rs | 378 +-------------------- src/librustc/query/mod.rs | 4 + src/librustc/session/config.rs | 2 +- src/librustc/session/mod.rs | 3 - src/librustc_codegen_ssa/back/link.rs | 61 ++-- src/librustc_codegen_ssa/back/linker.rs | 12 +- src/librustc_codegen_ssa/back/write.rs | 2 +- src/librustc_codegen_ssa/base.rs | 3 +- src/librustc_codegen_ssa/lib.rs | 2 + src/librustc_interface/passes.rs | 4 - src/librustc_metadata/cstore_impl.rs | 5 + src/librustc_metadata/dependency_format.rs | 371 ++++++++++++++++++++ src/librustc_metadata/encoder.rs | 26 +- src/librustc_metadata/lib.rs | 1 + 14 files changed, 455 insertions(+), 419 deletions(-) create mode 100644 src/librustc_metadata/dependency_format.rs diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index 96b99fe4cdce2..8b2bf55ccc120 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -1,64 +1,10 @@ -//! Resolution of mixing rlibs and dylibs +//! Type definitions for learning about the dependency formats of all upstream +//! crates (rlibs/dylibs/oh my). //! -//! When producing a final artifact, such as a dynamic library, the compiler has -//! a choice between linking an rlib or linking a dylib of all upstream -//! dependencies. The linking phase must guarantee, however, that a library only -//! show up once in the object file. For example, it is illegal for library A to -//! be statically linked to B and C in separate dylibs, and then link B and C -//! into a crate D (because library A appears twice). -//! -//! The job of this module is to calculate what format each upstream crate -//! should be used when linking each output type requested in this session. This -//! generally follows this set of rules: -//! -//! 1. Each library must appear exactly once in the output. -//! 2. Each rlib contains only one library (it's just an object file) -//! 3. Each dylib can contain more than one library (due to static linking), -//! and can also bring in many dynamic dependencies. -//! -//! With these constraints in mind, it's generally a very difficult problem to -//! find a solution that's not "all rlibs" or "all dylibs". I have suspicions -//! that NP-ness may come into the picture here... -//! -//! The current selection algorithm below looks mostly similar to: -//! -//! 1. If static linking is required, then require all upstream dependencies -//! to be available as rlibs. If not, generate an error. -//! 2. If static linking is requested (generating an executable), then -//! attempt to use all upstream dependencies as rlibs. If any are not -//! found, bail out and continue to step 3. -//! 3. Static linking has failed, at least one library must be dynamically -//! linked. Apply a heuristic by greedily maximizing the number of -//! dynamically linked libraries. -//! 4. Each upstream dependency available as a dynamic library is -//! registered. The dependencies all propagate, adding to a map. It is -//! possible for a dylib to add a static library as a dependency, but it -//! is illegal for two dylibs to add the same static library as a -//! dependency. The same dylib can be added twice. Additionally, it is -//! illegal to add a static dependency when it was previously found as a -//! dylib (and vice versa) -//! 5. After all dynamic dependencies have been traversed, re-traverse the -//! remaining dependencies and add them statically (if they haven't been -//! added already). -//! -//! While not perfect, this algorithm should help support use-cases such as leaf -//! dependencies being static while the larger tree of inner dependencies are -//! all dynamic. This isn't currently very well battle tested, so it will likely -//! fall short in some use cases. -//! -//! Currently, there is no way to specify the preference of linkage with a -//! particular library (other than a global dynamic/static switch). -//! Additionally, the algorithm is geared towards finding *any* solution rather -//! than finding a number of solutions (there are normally quite a few). - -use crate::hir::def_id::CrateNum; +//! For all the gory details, see the provider of the `dependency_formats` +//! query. use crate::session::config; -use crate::ty::TyCtxt; -use crate::middle::cstore::{self, DepKind}; -use crate::middle::cstore::LinkagePreference::{self, RequireStatic, RequireDynamic}; -use crate::util::nodemap::FxHashMap; -use rustc_target::spec::PanicStrategy; /// A list of dependencies for a certain crate type. /// @@ -71,324 +17,12 @@ pub type DependencyList = Vec; /// A mapping of all required dependencies for a particular flavor of output. /// /// This is local to the tcx, and is generally relevant to one session. -pub type Dependencies = FxHashMap; +pub type Dependencies = Vec<(config::CrateType, DependencyList)>; -#[derive(Copy, Clone, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug, HashStable)] pub enum Linkage { NotLinked, IncludedFromDylib, Static, Dynamic, } - -pub fn calculate(tcx: TyCtxt<'_>) { - let sess = &tcx.sess; - let fmts = sess.crate_types.borrow().iter().map(|&ty| { - let linkage = calculate_type(tcx, ty); - verify_ok(tcx, &linkage); - (ty, linkage) - }).collect::>(); - sess.abort_if_errors(); - sess.dependency_formats.set(fmts); -} - -fn calculate_type(tcx: TyCtxt<'_>, ty: config::CrateType) -> DependencyList { - let sess = &tcx.sess; - - if !sess.opts.output_types.should_codegen() { - return Vec::new(); - } - - let preferred_linkage = match ty { - // cdylibs must have all static dependencies. - config::CrateType::Cdylib => Linkage::Static, - - // Generating a dylib without `-C prefer-dynamic` means that we're going - // to try to eagerly statically link all dependencies. This is normally - // done for end-product dylibs, not intermediate products. - config::CrateType::Dylib if !sess.opts.cg.prefer_dynamic => Linkage::Static, - config::CrateType::Dylib => Linkage::Dynamic, - - // If the global prefer_dynamic switch is turned off, or the final - // executable will be statically linked, prefer static crate linkage. - config::CrateType::Executable if !sess.opts.cg.prefer_dynamic || - sess.crt_static() => Linkage::Static, - config::CrateType::Executable => Linkage::Dynamic, - - // proc-macro crates are mostly cdylibs, but we also need metadata. - config::CrateType::ProcMacro => Linkage::Static, - - // No linkage happens with rlibs, we just needed the metadata (which we - // got long ago), so don't bother with anything. - config::CrateType::Rlib => Linkage::NotLinked, - - // staticlibs must have all static dependencies. - config::CrateType::Staticlib => Linkage::Static, - }; - - if preferred_linkage == Linkage::NotLinked { - // If the crate is not linked, there are no link-time dependencies. - return Vec::new(); - } - - if preferred_linkage == Linkage::Static { - // Attempt static linkage first. For dylibs and executables, we may be - // able to retry below with dynamic linkage. - if let Some(v) = attempt_static(tcx) { - return v; - } - - // Staticlibs, cdylibs, and static executables must have all static - // dependencies. If any are not found, generate some nice pretty errors. - if ty == config::CrateType::Cdylib || ty == config::CrateType::Staticlib || - (ty == config::CrateType::Executable && sess.crt_static() && - !sess.target.target.options.crt_static_allows_dylibs) { - for &cnum in tcx.crates().iter() { - if tcx.dep_kind(cnum).macros_only() { continue } - let src = tcx.used_crate_source(cnum); - if src.rlib.is_some() { continue } - sess.err(&format!("crate `{}` required to be available in rlib format, \ - but was not found in this form", - tcx.crate_name(cnum))); - } - return Vec::new(); - } - } - - let mut formats = FxHashMap::default(); - - // Sweep all crates for found dylibs. Add all dylibs, as well as their - // dependencies, ensuring there are no conflicts. The only valid case for a - // dependency to be relied upon twice is for both cases to rely on a dylib. - for &cnum in tcx.crates().iter() { - if tcx.dep_kind(cnum).macros_only() { continue } - let name = tcx.crate_name(cnum); - let src = tcx.used_crate_source(cnum); - if src.dylib.is_some() { - info!("adding dylib: {}", name); - add_library(tcx, cnum, RequireDynamic, &mut formats); - let deps = tcx.dylib_dependency_formats(cnum); - for &(depnum, style) in deps.iter() { - info!("adding {:?}: {}", style, tcx.crate_name(depnum)); - add_library(tcx, depnum, style, &mut formats); - } - } - } - - // Collect what we've got so far in the return vector. - let last_crate = tcx.crates().len(); - let mut ret = (1..last_crate+1).map(|cnum| { - match formats.get(&CrateNum::new(cnum)) { - Some(&RequireDynamic) => Linkage::Dynamic, - Some(&RequireStatic) => Linkage::IncludedFromDylib, - None => Linkage::NotLinked, - } - }).collect::>(); - - // Run through the dependency list again, and add any missing libraries as - // static libraries. - // - // If the crate hasn't been included yet and it's not actually required - // (e.g., it's an allocator) then we skip it here as well. - for &cnum in tcx.crates().iter() { - let src = tcx.used_crate_source(cnum); - if src.dylib.is_none() && - !formats.contains_key(&cnum) && - tcx.dep_kind(cnum) == DepKind::Explicit { - assert!(src.rlib.is_some() || src.rmeta.is_some()); - info!("adding staticlib: {}", tcx.crate_name(cnum)); - add_library(tcx, cnum, RequireStatic, &mut formats); - ret[cnum.as_usize() - 1] = Linkage::Static; - } - } - - // We've gotten this far because we're emitting some form of a final - // artifact which means that we may need to inject dependencies of some - // form. - // - // Things like allocators and panic runtimes may not have been activated - // quite yet, so do so here. - activate_injected_dep(*sess.injected_panic_runtime.get(), &mut ret, - &|cnum| tcx.is_panic_runtime(cnum)); - - // When dylib B links to dylib A, then when using B we must also link to A. - // It could be the case, however, that the rlib for A is present (hence we - // found metadata), but the dylib for A has since been removed. - // - // For situations like this, we perform one last pass over the dependencies, - // making sure that everything is available in the requested format. - for (cnum, kind) in ret.iter().enumerate() { - let cnum = CrateNum::new(cnum + 1); - let src = tcx.used_crate_source(cnum); - match *kind { - Linkage::NotLinked | - Linkage::IncludedFromDylib => {} - Linkage::Static if src.rlib.is_some() => continue, - Linkage::Dynamic if src.dylib.is_some() => continue, - kind => { - let kind = match kind { - Linkage::Static => "rlib", - _ => "dylib", - }; - sess.err(&format!("crate `{}` required to be available in {} format, \ - but was not found in this form", - tcx.crate_name(cnum), kind)); - } - } - } - - ret -} - -fn add_library( - tcx: TyCtxt<'_>, - cnum: CrateNum, - link: LinkagePreference, - m: &mut FxHashMap, -) { - match m.get(&cnum) { - Some(&link2) => { - // If the linkages differ, then we'd have two copies of the library - // if we continued linking. If the linkages are both static, then we - // would also have two copies of the library (static from two - // different locations). - // - // This error is probably a little obscure, but I imagine that it - // can be refined over time. - if link2 != link || link == RequireStatic { - tcx.sess.struct_err(&format!("cannot satisfy dependencies so `{}` only \ - shows up once", tcx.crate_name(cnum))) - .help("having upstream crates all available in one format \ - will likely make this go away") - .emit(); - } - } - None => { m.insert(cnum, link); } - } -} - -fn attempt_static(tcx: TyCtxt<'_>) -> Option { - let sess = &tcx.sess; - let crates = cstore::used_crates(tcx, RequireStatic); - if !crates.iter().by_ref().all(|&(_, ref p)| p.is_some()) { - return None - } - - // All crates are available in an rlib format, so we're just going to link - // everything in explicitly so long as it's actually required. - let last_crate = tcx.crates().len(); - let mut ret = (1..last_crate+1).map(|cnum| { - if tcx.dep_kind(CrateNum::new(cnum)) == DepKind::Explicit { - Linkage::Static - } else { - Linkage::NotLinked - } - }).collect::>(); - - // Our allocator/panic runtime may not have been linked above if it wasn't - // explicitly linked, which is the case for any injected dependency. Handle - // that here and activate them. - activate_injected_dep(*sess.injected_panic_runtime.get(), &mut ret, - &|cnum| tcx.is_panic_runtime(cnum)); - - Some(ret) -} - -// Given a list of how to link upstream dependencies so far, ensure that an -// injected dependency is activated. This will not do anything if one was -// transitively included already (e.g., via a dylib or explicitly so). -// -// If an injected dependency was not found then we're guaranteed the -// metadata::creader module has injected that dependency (not listed as -// a required dependency) in one of the session's field. If this field is not -// set then this compilation doesn't actually need the dependency and we can -// also skip this step entirely. -fn activate_injected_dep(injected: Option, - list: &mut DependencyList, - replaces_injected: &dyn Fn(CrateNum) -> bool) { - for (i, slot) in list.iter().enumerate() { - let cnum = CrateNum::new(i + 1); - if !replaces_injected(cnum) { - continue - } - if *slot != Linkage::NotLinked { - return - } - } - if let Some(injected) = injected { - let idx = injected.as_usize() - 1; - assert_eq!(list[idx], Linkage::NotLinked); - list[idx] = Linkage::Static; - } -} - -// After the linkage for a crate has been determined we need to verify that -// there's only going to be one allocator in the output. -fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { - let sess = &tcx.sess; - if list.len() == 0 { - return - } - let mut panic_runtime = None; - for (i, linkage) in list.iter().enumerate() { - if let Linkage::NotLinked = *linkage { - continue - } - let cnum = CrateNum::new(i + 1); - - if tcx.is_panic_runtime(cnum) { - if let Some((prev, _)) = panic_runtime { - let prev_name = tcx.crate_name(prev); - let cur_name = tcx.crate_name(cnum); - sess.err(&format!("cannot link together two \ - panic runtimes: {} and {}", - prev_name, cur_name)); - } - panic_runtime = Some((cnum, tcx.panic_strategy(cnum))); - } - } - - // If we found a panic runtime, then we know by this point that it's the - // only one, but we perform validation here that all the panic strategy - // compilation modes for the whole DAG are valid. - if let Some((cnum, found_strategy)) = panic_runtime { - let desired_strategy = sess.panic_strategy(); - - // First up, validate that our selected panic runtime is indeed exactly - // our same strategy. - if found_strategy != desired_strategy { - sess.err(&format!("the linked panic runtime `{}` is \ - not compiled with this crate's \ - panic strategy `{}`", - tcx.crate_name(cnum), - desired_strategy.desc())); - } - - // Next up, verify that all other crates are compatible with this panic - // strategy. If the dep isn't linked, we ignore it, and if our strategy - // is abort then it's compatible with everything. Otherwise all crates' - // panic strategy must match our own. - for (i, linkage) in list.iter().enumerate() { - if let Linkage::NotLinked = *linkage { - continue - } - if desired_strategy == PanicStrategy::Abort { - continue - } - let cnum = CrateNum::new(i + 1); - let found_strategy = tcx.panic_strategy(cnum); - let is_compiler_builtins = tcx.is_compiler_builtins(cnum); - if is_compiler_builtins || desired_strategy == found_strategy { - continue - } - - sess.err(&format!("the crate `{}` is compiled with the \ - panic strategy `{}` which is \ - incompatible with this crate's \ - strategy of `{}`", - tcx.crate_name(cnum), - found_strategy.desc(), - desired_strategy.desc())); - } - } -} diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index c7260945295a6..4a9fa57f34525 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -630,6 +630,10 @@ rustc_queries! { -> &'tcx [(CrateNum, LinkagePreference)] { desc { "dylib dependency formats of crate" } } + + query dependency_formats(_: CrateNum) -> Lrc { + desc { "get the linkage format of all dependencies" } + } } Codegen { diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 5eda3df378126..a9a20a924347c 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -687,7 +687,7 @@ pub enum EntryFnType { impl_stable_hash_via_hash!(EntryFnType); -#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)] +#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, HashStable)] pub enum CrateType { Executable, Dylib, diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index a24fed8f21c5a..8aca861d1f64d 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -7,7 +7,6 @@ use rustc_data_structures::fingerprint::Fingerprint; use crate::lint; use crate::lint::builtin::BuiltinLintDiagnostics; -use crate::middle::dependency_format; use crate::session::config::{OutputType, PrintRequest, SwitchWithOptPath}; use crate::session::search_paths::{PathKind, SearchPath}; use crate::util::nodemap::{FxHashMap, FxHashSet}; @@ -91,7 +90,6 @@ pub struct Session { pub plugin_llvm_passes: OneThread>>, pub plugin_attributes: Lock>, pub crate_types: Once>, - pub dependency_formats: Once, /// The `crate_disambiguator` is constructed out of all the `-C metadata` /// arguments passed to the compiler. Its value together with the crate-name /// forms a unique global identifier for the crate. It is used to allow @@ -1247,7 +1245,6 @@ fn build_session_( plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())), plugin_attributes: Lock::new(Vec::new()), crate_types: Once::new(), - dependency_formats: Once::new(), crate_disambiguator: Once::new(), features: Once::new(), recursion_limit: Once::new(), diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 9b044d9b45377..3b7ae5e33d5e7 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -219,15 +219,24 @@ pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathB (linker.to_path_buf(), cmd) } -pub fn each_linked_rlib(sess: &Session, - info: &CrateInfo, - f: &mut dyn FnMut(CrateNum, &Path)) -> Result<(), String> { +pub fn each_linked_rlib( + info: &CrateInfo, + f: &mut dyn FnMut(CrateNum, &Path), +) -> Result<(), String> { let crates = info.used_crates_static.iter(); - let fmts = sess.dependency_formats.borrow(); - let fmts = fmts.get(&config::CrateType::Executable) - .or_else(|| fmts.get(&config::CrateType::Staticlib)) - .or_else(|| fmts.get(&config::CrateType::Cdylib)) - .or_else(|| fmts.get(&config::CrateType::ProcMacro)); + let mut fmts = None; + for (ty, list) in info.dependency_formats.iter() { + match ty { + config::CrateType::Executable | + config::CrateType::Staticlib | + config::CrateType::Cdylib | + config::CrateType::ProcMacro => { + fmts = Some(list); + break; + } + _ => {} + } + } let fmts = match fmts { Some(f) => f, None => return Err("could not find formats for rlibs".to_string()) @@ -406,7 +415,7 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(sess: &'a Session, tempdir); let mut all_native_libs = vec![]; - let res = each_linked_rlib(sess, &codegen_results.crate_info, &mut |cnum, path| { + let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| { let name = &codegen_results.crate_info.crate_name[&cnum]; let native_libs = &codegen_results.crate_info.native_libraries[&cnum]; @@ -1294,11 +1303,13 @@ pub fn add_local_native_libraries(cmd: &mut dyn Linker, // Rust crates are not considered at all when creating an rlib output. All // dependencies will be linked when producing the final output (instead of // the intermediate rlib version) -fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker, - sess: &'a Session, - codegen_results: &CodegenResults, - crate_type: config::CrateType, - tmpdir: &Path) { +fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( + cmd: &mut dyn Linker, + sess: &'a Session, + codegen_results: &CodegenResults, + crate_type: config::CrateType, + tmpdir: &Path, +) { // All of the heavy lifting has previously been accomplished by the // dependency_format module of the compiler. This is just crawling the // output of that module, adding crates as necessary. @@ -1307,8 +1318,10 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker, // will slurp up the object files inside), and linking to a dynamic library // involves just passing the right -l flag. - let formats = sess.dependency_formats.borrow(); - let data = formats.get(&crate_type).unwrap(); + let (_, data) = codegen_results.crate_info.dependency_formats + .iter() + .find(|(ty, _)| *ty == crate_type) + .expect("failed to find crate type in dependency format list"); // Invoke get_used_crates to ensure that we get a topological sorting of // crates. @@ -1620,10 +1633,12 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker, // generic function calls a native function, then the generic function must // be instantiated in the target crate, meaning that the native symbol must // also be resolved in the target crate. -pub fn add_upstream_native_libraries(cmd: &mut dyn Linker, - sess: &Session, - codegen_results: &CodegenResults, - crate_type: config::CrateType) { +pub fn add_upstream_native_libraries( + cmd: &mut dyn Linker, + sess: &Session, + codegen_results: &CodegenResults, + crate_type: config::CrateType, +) { // Be sure to use a topological sorting of crates because there may be // interdependencies between native libraries. When passing -nodefaultlibs, // for example, almost all native libraries depend on libc, so we have to @@ -1633,8 +1648,10 @@ pub fn add_upstream_native_libraries(cmd: &mut dyn Linker, // This passes RequireStatic, but the actual requirement doesn't matter, // we're just getting an ordering of crate numbers, we're not worried about // the paths. - let formats = sess.dependency_formats.borrow(); - let data = formats.get(&crate_type).unwrap(); + let (_, data) = codegen_results.crate_info.dependency_formats + .iter() + .find(|(ty, _)| *ty == crate_type) + .expect("failed to find crate type in dependency format list"); let crates = &codegen_results.crate_info.used_crates_static; for &(cnum, _) in crates { diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index c42cd024926dc..940a9a72bf6d4 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -1092,10 +1092,16 @@ fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec { } } - let formats = tcx.sess.dependency_formats.borrow(); - let deps = formats[&crate_type].iter(); + let formats = tcx.dependency_formats(LOCAL_CRATE); + let deps = formats.iter().filter_map(|(t, list)| { + if *t == crate_type { + Some(list) + } else { + None + } + }).next().unwrap(); - for (index, dep_format) in deps.enumerate() { + for (index, dep_format) in deps.iter().enumerate() { let cnum = CrateNum::new(index + 1); // For each dependency that we are linking to statically ... if *dep_format == Linkage::Static { diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 1bba479c1fd5d..1a2c23ae0d4f7 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -1048,7 +1048,7 @@ fn start_executing_work( }).expect("failed to spawn helper thread"); let mut each_linked_rlib_for_lto = Vec::new(); - drop(link::each_linked_rlib(sess, crate_info, &mut |cnum, path| { + drop(link::each_linked_rlib(crate_info, &mut |cnum, path| { if link::ignored_for_lto(sess, crate_info, cnum) { return } diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 4acbe0356b47c..98d3022a4185d 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -539,7 +539,7 @@ pub fn codegen_crate( // linkage, then it's already got an allocator shim and we'll be using that // one instead. If nothing exists then it's our job to generate the // allocator! - let any_dynamic_crate = tcx.sess.dependency_formats.borrow() + let any_dynamic_crate = tcx.dependency_formats(LOCAL_CRATE) .iter() .any(|(_, list)| { use rustc::middle::dependency_format::Linkage; @@ -731,6 +731,7 @@ impl CrateInfo { used_crate_source: Default::default(), lang_item_to_crate: Default::default(), missing_lang_items: Default::default(), + dependency_formats: tcx.dependency_formats(LOCAL_CRATE), }; let lang_items = tcx.lang_items(); diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index 1708d7235b45b..161d3ce61f0a6 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -33,6 +33,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::svh::Svh; use rustc::middle::cstore::{LibSource, CrateSource, NativeLibrary}; +use rustc::middle::dependency_format::Dependencies; use syntax_pos::symbol::Symbol; mod error_codes; @@ -142,6 +143,7 @@ pub struct CrateInfo { pub used_crates_dynamic: Vec<(CrateNum, LibSource)>, pub lang_item_to_crate: FxHashMap, pub missing_lang_items: FxHashMap>, + pub dependency_formats: Lrc, } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index e8e8da6733471..102ea690f5ac9 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -1079,10 +1079,6 @@ pub fn start_codegen<'tcx>( tcx.print_debug_stats(); } - time(tcx.sess, "resolving dependency formats", || { - middle::dependency_format::calculate(tcx) - }); - let (metadata, need_metadata_module) = time(tcx.sess, "metadata encoding and writing", || { encode_and_write_metadata(tcx, outputs) }); diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index a1e3bbcbf8ea9..4a81fd3b32084 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -370,6 +370,11 @@ pub fn provide(providers: &mut Providers<'_>) { tcx.arena.alloc(visible_parent_map) }, + dependency_formats: |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + Lrc::new(crate::dependency_format::calculate(tcx)) + }, + ..*providers }; } diff --git a/src/librustc_metadata/dependency_format.rs b/src/librustc_metadata/dependency_format.rs new file mode 100644 index 0000000000000..9de326a67b423 --- /dev/null +++ b/src/librustc_metadata/dependency_format.rs @@ -0,0 +1,371 @@ +//! Resolution of mixing rlibs and dylibs +//! +//! When producing a final artifact, such as a dynamic library, the compiler has +//! a choice between linking an rlib or linking a dylib of all upstream +//! dependencies. The linking phase must guarantee, however, that a library only +//! show up once in the object file. For example, it is illegal for library A to +//! be statically linked to B and C in separate dylibs, and then link B and C +//! into a crate D (because library A appears twice). +//! +//! The job of this module is to calculate what format each upstream crate +//! should be used when linking each output type requested in this session. This +//! generally follows this set of rules: +//! +//! 1. Each library must appear exactly once in the output. +//! 2. Each rlib contains only one library (it's just an object file) +//! 3. Each dylib can contain more than one library (due to static linking), +//! and can also bring in many dynamic dependencies. +//! +//! With these constraints in mind, it's generally a very difficult problem to +//! find a solution that's not "all rlibs" or "all dylibs". I have suspicions +//! that NP-ness may come into the picture here... +//! +//! The current selection algorithm below looks mostly similar to: +//! +//! 1. If static linking is required, then require all upstream dependencies +//! to be available as rlibs. If not, generate an error. +//! 2. If static linking is requested (generating an executable), then +//! attempt to use all upstream dependencies as rlibs. If any are not +//! found, bail out and continue to step 3. +//! 3. Static linking has failed, at least one library must be dynamically +//! linked. Apply a heuristic by greedily maximizing the number of +//! dynamically linked libraries. +//! 4. Each upstream dependency available as a dynamic library is +//! registered. The dependencies all propagate, adding to a map. It is +//! possible for a dylib to add a static library as a dependency, but it +//! is illegal for two dylibs to add the same static library as a +//! dependency. The same dylib can be added twice. Additionally, it is +//! illegal to add a static dependency when it was previously found as a +//! dylib (and vice versa) +//! 5. After all dynamic dependencies have been traversed, re-traverse the +//! remaining dependencies and add them statically (if they haven't been +//! added already). +//! +//! While not perfect, this algorithm should help support use-cases such as leaf +//! dependencies being static while the larger tree of inner dependencies are +//! all dynamic. This isn't currently very well battle tested, so it will likely +//! fall short in some use cases. +//! +//! Currently, there is no way to specify the preference of linkage with a +//! particular library (other than a global dynamic/static switch). +//! Additionally, the algorithm is geared towards finding *any* solution rather +//! than finding a number of solutions (there are normally quite a few). + +use rustc::hir::def_id::CrateNum; +use rustc::middle::cstore::LinkagePreference::{self, RequireStatic, RequireDynamic}; +use rustc::middle::cstore::{self, DepKind}; +use rustc::middle::dependency_format::{DependencyList, Dependencies, Linkage}; +use rustc::session::config; +use rustc::ty::TyCtxt; +use rustc::util::nodemap::FxHashMap; +use rustc_target::spec::PanicStrategy; + +pub fn calculate(tcx: TyCtxt<'_>) -> Dependencies { + tcx.sess.crate_types.borrow().iter().map(|&ty| { + let linkage = calculate_type(tcx, ty); + verify_ok(tcx, &linkage); + (ty, linkage) + }).collect::>() +} + +fn calculate_type(tcx: TyCtxt<'_>, ty: config::CrateType) -> DependencyList { + let sess = &tcx.sess; + + if !sess.opts.output_types.should_codegen() { + return Vec::new(); + } + + let preferred_linkage = match ty { + // cdylibs must have all static dependencies. + config::CrateType::Cdylib => Linkage::Static, + + // Generating a dylib without `-C prefer-dynamic` means that we're going + // to try to eagerly statically link all dependencies. This is normally + // done for end-product dylibs, not intermediate products. + config::CrateType::Dylib if !sess.opts.cg.prefer_dynamic => Linkage::Static, + config::CrateType::Dylib => Linkage::Dynamic, + + // If the global prefer_dynamic switch is turned off, or the final + // executable will be statically linked, prefer static crate linkage. + config::CrateType::Executable if !sess.opts.cg.prefer_dynamic || + sess.crt_static() => Linkage::Static, + config::CrateType::Executable => Linkage::Dynamic, + + // proc-macro crates are mostly cdylibs, but we also need metadata. + config::CrateType::ProcMacro => Linkage::Static, + + // No linkage happens with rlibs, we just needed the metadata (which we + // got long ago), so don't bother with anything. + config::CrateType::Rlib => Linkage::NotLinked, + + // staticlibs must have all static dependencies. + config::CrateType::Staticlib => Linkage::Static, + }; + + if preferred_linkage == Linkage::NotLinked { + // If the crate is not linked, there are no link-time dependencies. + return Vec::new(); + } + + if preferred_linkage == Linkage::Static { + // Attempt static linkage first. For dylibs and executables, we may be + // able to retry below with dynamic linkage. + if let Some(v) = attempt_static(tcx) { + return v; + } + + // Staticlibs, cdylibs, and static executables must have all static + // dependencies. If any are not found, generate some nice pretty errors. + if ty == config::CrateType::Cdylib || ty == config::CrateType::Staticlib || + (ty == config::CrateType::Executable && sess.crt_static() && + !sess.target.target.options.crt_static_allows_dylibs) { + for &cnum in tcx.crates().iter() { + if tcx.dep_kind(cnum).macros_only() { continue } + let src = tcx.used_crate_source(cnum); + if src.rlib.is_some() { continue } + sess.err(&format!("crate `{}` required to be available in rlib format, \ + but was not found in this form", + tcx.crate_name(cnum))); + } + return Vec::new(); + } + } + + let mut formats = FxHashMap::default(); + + // Sweep all crates for found dylibs. Add all dylibs, as well as their + // dependencies, ensuring there are no conflicts. The only valid case for a + // dependency to be relied upon twice is for both cases to rely on a dylib. + for &cnum in tcx.crates().iter() { + if tcx.dep_kind(cnum).macros_only() { continue } + let name = tcx.crate_name(cnum); + let src = tcx.used_crate_source(cnum); + if src.dylib.is_some() { + log::info!("adding dylib: {}", name); + add_library(tcx, cnum, RequireDynamic, &mut formats); + let deps = tcx.dylib_dependency_formats(cnum); + for &(depnum, style) in deps.iter() { + log::info!("adding {:?}: {}", style, tcx.crate_name(depnum)); + add_library(tcx, depnum, style, &mut formats); + } + } + } + + // Collect what we've got so far in the return vector. + let last_crate = tcx.crates().len(); + let mut ret = (1..last_crate+1).map(|cnum| { + match formats.get(&CrateNum::new(cnum)) { + Some(&RequireDynamic) => Linkage::Dynamic, + Some(&RequireStatic) => Linkage::IncludedFromDylib, + None => Linkage::NotLinked, + } + }).collect::>(); + + // Run through the dependency list again, and add any missing libraries as + // static libraries. + // + // If the crate hasn't been included yet and it's not actually required + // (e.g., it's an allocator) then we skip it here as well. + for &cnum in tcx.crates().iter() { + let src = tcx.used_crate_source(cnum); + if src.dylib.is_none() && + !formats.contains_key(&cnum) && + tcx.dep_kind(cnum) == DepKind::Explicit { + assert!(src.rlib.is_some() || src.rmeta.is_some()); + log::info!("adding staticlib: {}", tcx.crate_name(cnum)); + add_library(tcx, cnum, RequireStatic, &mut formats); + ret[cnum.as_usize() - 1] = Linkage::Static; + } + } + + // We've gotten this far because we're emitting some form of a final + // artifact which means that we may need to inject dependencies of some + // form. + // + // Things like allocators and panic runtimes may not have been activated + // quite yet, so do so here. + activate_injected_dep(*sess.injected_panic_runtime.get(), &mut ret, + &|cnum| tcx.is_panic_runtime(cnum)); + + // When dylib B links to dylib A, then when using B we must also link to A. + // It could be the case, however, that the rlib for A is present (hence we + // found metadata), but the dylib for A has since been removed. + // + // For situations like this, we perform one last pass over the dependencies, + // making sure that everything is available in the requested format. + for (cnum, kind) in ret.iter().enumerate() { + let cnum = CrateNum::new(cnum + 1); + let src = tcx.used_crate_source(cnum); + match *kind { + Linkage::NotLinked | + Linkage::IncludedFromDylib => {} + Linkage::Static if src.rlib.is_some() => continue, + Linkage::Dynamic if src.dylib.is_some() => continue, + kind => { + let kind = match kind { + Linkage::Static => "rlib", + _ => "dylib", + }; + sess.err(&format!("crate `{}` required to be available in {} format, \ + but was not found in this form", + tcx.crate_name(cnum), kind)); + } + } + } + + ret +} + +fn add_library( + tcx: TyCtxt<'_>, + cnum: CrateNum, + link: LinkagePreference, + m: &mut FxHashMap, +) { + match m.get(&cnum) { + Some(&link2) => { + // If the linkages differ, then we'd have two copies of the library + // if we continued linking. If the linkages are both static, then we + // would also have two copies of the library (static from two + // different locations). + // + // This error is probably a little obscure, but I imagine that it + // can be refined over time. + if link2 != link || link == RequireStatic { + tcx.sess.struct_err(&format!("cannot satisfy dependencies so `{}` only \ + shows up once", tcx.crate_name(cnum))) + .help("having upstream crates all available in one format \ + will likely make this go away") + .emit(); + } + } + None => { m.insert(cnum, link); } + } +} + +fn attempt_static(tcx: TyCtxt<'_>) -> Option { + let sess = &tcx.sess; + let crates = cstore::used_crates(tcx, RequireStatic); + if !crates.iter().by_ref().all(|&(_, ref p)| p.is_some()) { + return None + } + + // All crates are available in an rlib format, so we're just going to link + // everything in explicitly so long as it's actually required. + let last_crate = tcx.crates().len(); + let mut ret = (1..last_crate+1).map(|cnum| { + if tcx.dep_kind(CrateNum::new(cnum)) == DepKind::Explicit { + Linkage::Static + } else { + Linkage::NotLinked + } + }).collect::>(); + + // Our allocator/panic runtime may not have been linked above if it wasn't + // explicitly linked, which is the case for any injected dependency. Handle + // that here and activate them. + activate_injected_dep(*sess.injected_panic_runtime.get(), &mut ret, + &|cnum| tcx.is_panic_runtime(cnum)); + + Some(ret) +} + +// Given a list of how to link upstream dependencies so far, ensure that an +// injected dependency is activated. This will not do anything if one was +// transitively included already (e.g., via a dylib or explicitly so). +// +// If an injected dependency was not found then we're guaranteed the +// metadata::creader module has injected that dependency (not listed as +// a required dependency) in one of the session's field. If this field is not +// set then this compilation doesn't actually need the dependency and we can +// also skip this step entirely. +fn activate_injected_dep(injected: Option, + list: &mut DependencyList, + replaces_injected: &dyn Fn(CrateNum) -> bool) { + for (i, slot) in list.iter().enumerate() { + let cnum = CrateNum::new(i + 1); + if !replaces_injected(cnum) { + continue + } + if *slot != Linkage::NotLinked { + return + } + } + if let Some(injected) = injected { + let idx = injected.as_usize() - 1; + assert_eq!(list[idx], Linkage::NotLinked); + list[idx] = Linkage::Static; + } +} + +// After the linkage for a crate has been determined we need to verify that +// there's only going to be one allocator in the output. +fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { + let sess = &tcx.sess; + if list.len() == 0 { + return + } + let mut panic_runtime = None; + for (i, linkage) in list.iter().enumerate() { + if let Linkage::NotLinked = *linkage { + continue + } + let cnum = CrateNum::new(i + 1); + + if tcx.is_panic_runtime(cnum) { + if let Some((prev, _)) = panic_runtime { + let prev_name = tcx.crate_name(prev); + let cur_name = tcx.crate_name(cnum); + sess.err(&format!("cannot link together two \ + panic runtimes: {} and {}", + prev_name, cur_name)); + } + panic_runtime = Some((cnum, tcx.panic_strategy(cnum))); + } + } + + // If we found a panic runtime, then we know by this point that it's the + // only one, but we perform validation here that all the panic strategy + // compilation modes for the whole DAG are valid. + if let Some((cnum, found_strategy)) = panic_runtime { + let desired_strategy = sess.panic_strategy(); + + // First up, validate that our selected panic runtime is indeed exactly + // our same strategy. + if found_strategy != desired_strategy { + sess.err(&format!("the linked panic runtime `{}` is \ + not compiled with this crate's \ + panic strategy `{}`", + tcx.crate_name(cnum), + desired_strategy.desc())); + } + + // Next up, verify that all other crates are compatible with this panic + // strategy. If the dep isn't linked, we ignore it, and if our strategy + // is abort then it's compatible with everything. Otherwise all crates' + // panic strategy must match our own. + for (i, linkage) in list.iter().enumerate() { + if let Linkage::NotLinked = *linkage { + continue + } + if desired_strategy == PanicStrategy::Abort { + continue + } + let cnum = CrateNum::new(i + 1); + let found_strategy = tcx.panic_strategy(cnum); + let is_compiler_builtins = tcx.is_compiler_builtins(cnum); + if is_compiler_builtins || desired_strategy == found_strategy { + continue + } + + sess.err(&format!("the crate `{}` is compiled with the \ + panic strategy `{}` which is \ + incompatible with this crate's \ + strategy of `{}`", + tcx.crate_name(cnum), + found_strategy.desc(), + desired_strategy.desc())); + } + } +} + diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index f430f01542efe..be083cf6020ea 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1649,20 +1649,22 @@ impl EncodeContext<'tcx> { } fn encode_dylib_dependency_formats(&mut self) -> Lazy<[Option]> { - match self.tcx.sess.dependency_formats.borrow().get(&config::CrateType::Dylib) { - Some(arr) => { - self.lazy(arr.iter().map(|slot| { - match *slot { - Linkage::NotLinked | - Linkage::IncludedFromDylib => None, - - Linkage::Dynamic => Some(LinkagePreference::RequireDynamic), - Linkage::Static => Some(LinkagePreference::RequireStatic), - } - })) + let formats = self.tcx.dependency_formats(LOCAL_CRATE); + for (ty, arr) in formats.iter() { + if *ty != config::CrateType::Dylib { + continue; } - None => Lazy::empty(), + return self.lazy(arr.iter().map(|slot| { + match *slot { + Linkage::NotLinked | + Linkage::IncludedFromDylib => None, + + Linkage::Dynamic => Some(LinkagePreference::RequireDynamic), + Linkage::Static => Some(LinkagePreference::RequireStatic), + } + })); } + Lazy::empty() } fn encode_info_for_foreign_item(&mut self, diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index e6104e629e9fb..9273b064ba9ce 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -32,6 +32,7 @@ mod schema; mod native_libs; mod link_args; mod foreign_modules; +mod dependency_format; pub mod creader; pub mod cstore; From 50c57d8c80b1fab4c1e9087756fb9fae396d5218 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 11 Sep 2019 08:08:04 -0700 Subject: [PATCH 127/413] rustc: Fix mixing crates with different `share_generics` This commit addresses #64319 by removing the `dylib` crate type from the list of crate type that exports generic symbols. The bug in #64319 arises because a `dylib` crate type was trying to export a symbol in an uptream crate but it miscalculated the symbol name of the uptream symbol. This isn't really necessary, though, since `dylib` crates aren't that heavily used, so we can just conservatively say that the `dylib` crate type never exports generic symbols, forcibly removing them from the exported symbol lists if were to otherwise find them. The fix here happens in two places: * First is in the `local_crate_exports_generics` method, indicating that it's now `false` for the `Dylib` crate type. Only rlibs actually export generics at this point. * Next is when we load exported symbols from upstream crate. If, for our compilation session, the crate may be included from a dynamic library, then its generic symbols are removed. When the crate was linked into a dynamic library its symbols weren't exported, so we can't consider them a candidate to link against. Overally this should avoid situations where we incorrectly calculate the upstream symbol names in the face of differnet `share_generics` options, ultimately... Closes #64319 --- src/librustc/query/mod.rs | 4 +- src/librustc/ty/context.rs | 4 +- .../back/symbol_export.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 27 ++++++++++++- src/librustc_metadata/dependency_format.rs | 1 - .../auxiliary/shared_generics_aux.rs | 1 + .../partitioning/shared-generics.rs | 1 + src/test/compile-fail/two-panic-runtimes.rs | 1 + .../run-make-fulldeps/issue-64319/Makefile | 39 +++++++++++++++++++ src/test/run-make-fulldeps/issue-64319/bar.rs | 5 +++ src/test/run-make-fulldeps/issue-64319/foo.rs | 9 +++++ .../symbol-visibility/Makefile | 4 +- .../panic-runtime/transitive-link-a-bunch.rs | 3 +- .../ui/panic-runtime/want-unwind-got-abort.rs | 3 +- .../panic-runtime/want-unwind-got-abort2.rs | 3 +- 15 files changed, 93 insertions(+), 14 deletions(-) create mode 100644 src/test/run-make-fulldeps/issue-64319/Makefile create mode 100644 src/test/run-make-fulldeps/issue-64319/bar.rs create mode 100644 src/test/run-make-fulldeps/issue-64319/foo.rs diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 4a9fa57f34525..fd99995480a9e 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -631,7 +631,9 @@ rustc_queries! { desc { "dylib dependency formats of crate" } } - query dependency_formats(_: CrateNum) -> Lrc { + query dependency_formats(_: CrateNum) + -> Lrc + { desc { "get the linkage format of all dependencies" } } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 0155803e30580..c03dbb2b1ed0e 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1510,9 +1510,9 @@ impl<'tcx> TyCtxt<'tcx> { CrateType::Executable | CrateType::Staticlib | CrateType::ProcMacro | + CrateType::Dylib | CrateType::Cdylib => false, - CrateType::Rlib | - CrateType::Dylib => true, + CrateType::Rlib => true, } }) } diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index 7e700e6819426..3e4b7695447c8 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -298,7 +298,7 @@ fn upstream_monomorphizations_provider( }; for &cnum in cnums.iter() { - for &(ref exported_symbol, _) in tcx.exported_symbols(cnum).iter() { + for (exported_symbol, _) in tcx.exported_symbols(cnum).iter() { if let &ExportedSymbol::Generic(def_id, substs) = exported_symbol { let substs_map = instances.entry(def_id).or_default(); diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 4a81fd3b32084..f18a98ffea7cd 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -10,6 +10,8 @@ use rustc::middle::cstore::{CrateStore, DepKind, EncodedMetadata, NativeLibraryKind}; use rustc::middle::exported_symbols::ExportedSymbol; use rustc::middle::stability::DeprecationEntry; +use rustc::middle::dependency_format::Linkage; +use rustc::session::config::CrateType; use rustc::hir::def; use rustc::hir; use rustc::session::{CrateDisambiguator, Session}; @@ -239,7 +241,30 @@ provide! { <'tcx> tcx, def_id, other, cdata, used_crate_source => { Lrc::new(cdata.source.clone()) } - exported_symbols => { Arc::new(cdata.exported_symbols(tcx)) } + exported_symbols => { + let mut syms = cdata.exported_symbols(tcx); + + // When linked into a dylib crates don't export their generic symbols, + // so if that's happening then we can't load upstream monomorphizations + // from this crate. As a result, if we're creating a dylib or this crate + // is being included from a different dynamic library, then we filter + // out all `Generic` symbols here. + let formats = tcx.dependency_formats(LOCAL_CRATE); + let remove_generics = formats.iter().any(|(ty, list)| { + *ty == CrateType::Dylib || + list.get(def_id.krate.as_usize() - 1) == Some(&Linkage::IncludedFromDylib) + }); + if remove_generics { + syms.retain(|(sym, _threshold)| { + match sym { + ExportedSymbol::Generic(..) => false, + _ => return true, + } + }); + } + + Arc::new(syms) + } } pub fn provide(providers: &mut Providers<'_>) { diff --git a/src/librustc_metadata/dependency_format.rs b/src/librustc_metadata/dependency_format.rs index 9de326a67b423..9a30623b33d62 100644 --- a/src/librustc_metadata/dependency_format.rs +++ b/src/librustc_metadata/dependency_format.rs @@ -368,4 +368,3 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { } } } - diff --git a/src/test/codegen-units/partitioning/auxiliary/shared_generics_aux.rs b/src/test/codegen-units/partitioning/auxiliary/shared_generics_aux.rs index d50a7910fe0b3..9050e8f1671d9 100644 --- a/src/test/codegen-units/partitioning/auxiliary/shared_generics_aux.rs +++ b/src/test/codegen-units/partitioning/auxiliary/shared_generics_aux.rs @@ -1,4 +1,5 @@ // compile-flags:-Zshare-generics=yes +// no-prefer-dynamic #![crate_type="rlib"] diff --git a/src/test/codegen-units/partitioning/shared-generics.rs b/src/test/codegen-units/partitioning/shared-generics.rs index 010412b8baeb3..58e485be00321 100644 --- a/src/test/codegen-units/partitioning/shared-generics.rs +++ b/src/test/codegen-units/partitioning/shared-generics.rs @@ -1,4 +1,5 @@ // ignore-tidy-linelength +// no-prefer-dynamic // compile-flags:-Zprint-mono-items=eager -Zshare-generics=yes -Zincremental=tmp/partitioning-tests/shared-generics-exe #![crate_type="rlib"] diff --git a/src/test/compile-fail/two-panic-runtimes.rs b/src/test/compile-fail/two-panic-runtimes.rs index 66b184e521abc..671d44564e66f 100644 --- a/src/test/compile-fail/two-panic-runtimes.rs +++ b/src/test/compile-fail/two-panic-runtimes.rs @@ -5,6 +5,7 @@ // aux-build:panic-runtime-lang-items.rs #![no_std] +#![no_main] extern crate panic_runtime_unwind; extern crate panic_runtime_unwind2; diff --git a/src/test/run-make-fulldeps/issue-64319/Makefile b/src/test/run-make-fulldeps/issue-64319/Makefile new file mode 100644 index 0000000000000..b2c6b8b3cbbf2 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-64319/Makefile @@ -0,0 +1,39 @@ +-include ../tools.mk + +# Different optimization levels imply different values for `-Zshare-generics`, +# so try out a whole bunch of combinations to make sure everything is compatible +all: + # First up, try some defaults + $(RUSTC) --crate-type rlib foo.rs + $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 + + # Next try mixing up some things explicitly + $(RUSTC) --crate-type rlib foo.rs -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no + $(RUSTC) --crate-type rlib foo.rs -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes + $(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no + $(RUSTC) --crate-type rlib foo.rs -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes + + # Now combine a whole bunch of options together + $(RUSTC) --crate-type rlib foo.rs + $(RUSTC) --crate-type dylib bar.rs + $(RUSTC) --crate-type dylib bar.rs -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -C opt-level=1 + $(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -C opt-level=1 -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -C opt-level=2 + $(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -C opt-level=2 -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 + $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -C opt-level=3 -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -C opt-level=s + $(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -C opt-level=s -Z share-generics=yes + $(RUSTC) --crate-type dylib bar.rs -C opt-level=z + $(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=no + $(RUSTC) --crate-type dylib bar.rs -C opt-level=z -Z share-generics=yes diff --git a/src/test/run-make-fulldeps/issue-64319/bar.rs b/src/test/run-make-fulldeps/issue-64319/bar.rs new file mode 100644 index 0000000000000..3895c0b6cdbb3 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-64319/bar.rs @@ -0,0 +1,5 @@ +extern crate foo; + +pub fn bar() { + foo::foo(); +} diff --git a/src/test/run-make-fulldeps/issue-64319/foo.rs b/src/test/run-make-fulldeps/issue-64319/foo.rs new file mode 100644 index 0000000000000..c54a238e9add7 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-64319/foo.rs @@ -0,0 +1,9 @@ +pub fn foo() { + bar::(); +} + +pub fn bar() { + baz(); +} + +fn baz() {} diff --git a/src/test/run-make-fulldeps/symbol-visibility/Makefile b/src/test/run-make-fulldeps/symbol-visibility/Makefile index 7901866015bf2..840fe801a953c 100644 --- a/src/test/run-make-fulldeps/symbol-visibility/Makefile +++ b/src/test/run-make-fulldeps/symbol-visibility/Makefile @@ -79,12 +79,12 @@ all: # Check that a Rust dylib exports its monomorphic functions, including generics this time [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_c_function_from_rust_dylib)" -eq "1" ] [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_rust_function_from_rust_dylib)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rust_dylib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rust_dylib)" -eq "0" ] # Check that a Rust dylib exports the monomorphic functions from its dependencies [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_c_function_from_rlib)" -eq "1" ] [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_rust_function_from_rlib)" -eq "1" ] - [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rlib)" -eq "1" ] + [ "$$($(NM) $(TMPDIR)/$(RDYLIB_NAME) | grep -c public_generic_function_from_rlib)" -eq "0" ] # Check that an executable does not export any dynamic symbols [ "$$($(NM) $(TMPDIR)/$(EXE_NAME) | grep -c public_c_function_from_rlib)" -eq "0" ] diff --git a/src/test/ui/panic-runtime/transitive-link-a-bunch.rs b/src/test/ui/panic-runtime/transitive-link-a-bunch.rs index 9b083a640a6d3..5d72771c2dcff 100644 --- a/src/test/ui/panic-runtime/transitive-link-a-bunch.rs +++ b/src/test/ui/panic-runtime/transitive-link-a-bunch.rs @@ -7,9 +7,8 @@ // ignore-wasm32-bare compiled with panic=abort by default #![no_std] +#![no_main] extern crate wants_panic_runtime_unwind; extern crate wants_panic_runtime_abort; extern crate panic_runtime_lang_items; - -fn main() {} diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort.rs b/src/test/ui/panic-runtime/want-unwind-got-abort.rs index c9ee8a032a3d3..4c25c09d6438f 100644 --- a/src/test/ui/panic-runtime/want-unwind-got-abort.rs +++ b/src/test/ui/panic-runtime/want-unwind-got-abort.rs @@ -4,8 +4,7 @@ // ignore-wasm32-bare compiled with panic=abort by default #![no_std] +#![no_main] extern crate panic_runtime_abort; extern crate panic_runtime_lang_items; - -fn main() {} diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort2.rs b/src/test/ui/panic-runtime/want-unwind-got-abort2.rs index 5219826eec62f..478af451e7f65 100644 --- a/src/test/ui/panic-runtime/want-unwind-got-abort2.rs +++ b/src/test/ui/panic-runtime/want-unwind-got-abort2.rs @@ -5,8 +5,7 @@ // ignore-wasm32-bare compiled with panic=abort by default #![no_std] +#![no_main] extern crate wants_panic_runtime_abort; extern crate panic_runtime_lang_items; - -fn main() {} From 8acf95886b6d045a5069b3a0c2c5f0fc29b1dc35 Mon Sep 17 00:00:00 2001 From: Andrew Banchich Date: Mon, 23 Sep 2019 16:09:36 -0400 Subject: [PATCH 128/413] update test Use assert_eq and assert_ne over comparison operators. --- src/libcore/mem/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 87ec05a243d36..8767625d4ed37 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -818,9 +818,9 @@ impl fmt::Debug for Discriminant { /// /// enum Foo { A(&'static str), B(i32), C(i32) } /// -/// assert!(mem::discriminant(&Foo::A("bar")) == mem::discriminant(&Foo::A("baz"))); -/// assert!(mem::discriminant(&Foo::B(1)) == mem::discriminant(&Foo::B(2))); -/// assert!(mem::discriminant(&Foo::B(3)) != mem::discriminant(&Foo::C(3))); +/// assert_eq!(mem::discriminant(&Foo::A("bar")), mem::discriminant(&Foo::A("baz"))); +/// assert_eq!(mem::discriminant(&Foo::B(1)), mem::discriminant(&Foo::B(2))); +/// assert_ne!(mem::discriminant(&Foo::B(3)), mem::discriminant(&Foo::C(3))); /// ``` #[stable(feature = "discriminant_value", since = "1.21.0")] pub fn discriminant(v: &T) -> Discriminant { From f70665a84692a80a820fccdaed19df5dde94c533 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 23 Sep 2019 22:28:14 +0200 Subject: [PATCH 129/413] cleanup librustc_errors Handler code. --- src/librustc_errors/lib.rs | 301 +++++++++++++++------------ src/librustc_typeck/check/wfcheck.rs | 2 +- src/libsyntax/ext/base.rs | 4 - src/libsyntax/ext/expand.rs | 2 +- src/libsyntax_ext/format.rs | 4 +- 5 files changed, 170 insertions(+), 143 deletions(-) diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index cdaa528e8e497..c01dcd94c725e 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -302,6 +302,9 @@ pub struct Handler { inner: Lock, } +/// This inner struct exists to keep it all behind a single lock; +/// this is done to prevent possible deadlocks in a multi-threaded compiler, +/// as well as inconsistent state observation. struct HandlerInner { flags: HandlerFlags, /// The number of errors that have been emitted, including duplicates. @@ -382,52 +385,65 @@ impl Drop for HandlerInner { } impl Handler { - pub fn with_tty_emitter(color_config: ColorConfig, - can_emit_warnings: bool, - treat_err_as_bug: Option, - cm: Option>) - -> Handler { - Handler::with_tty_emitter_and_flags( + pub fn with_tty_emitter( + color_config: ColorConfig, + can_emit_warnings: bool, + treat_err_as_bug: Option, + cm: Option>, + ) -> Self { + Self::with_tty_emitter_and_flags( color_config, cm, HandlerFlags { can_emit_warnings, treat_err_as_bug, .. Default::default() - }) + }, + ) } - pub fn with_tty_emitter_and_flags(color_config: ColorConfig, - cm: Option>, - flags: HandlerFlags) - -> Handler { + pub fn with_tty_emitter_and_flags( + color_config: ColorConfig, + cm: Option>, + flags: HandlerFlags, + ) -> Self { let emitter = Box::new(EmitterWriter::stderr( - color_config, cm, false, false, None, flags.external_macro_backtrace)); - Handler::with_emitter_and_flags(emitter, flags) - } - - pub fn with_emitter(can_emit_warnings: bool, - treat_err_as_bug: Option, - e: Box) - -> Handler { + color_config, + cm, + false, + false, + None, + flags.external_macro_backtrace, + )); + Self::with_emitter_and_flags(emitter, flags) + } + + pub fn with_emitter( + can_emit_warnings: bool, + treat_err_as_bug: Option, + emitter: Box, + ) -> Self { Handler::with_emitter_and_flags( - e, + emitter, HandlerFlags { can_emit_warnings, treat_err_as_bug, .. Default::default() - }) + }, + ) } - pub fn with_emitter_and_flags(e: Box, flags: HandlerFlags) -> Handler - { - Handler { + pub fn with_emitter_and_flags( + emitter: Box, + flags: HandlerFlags + ) -> Self { + Self { flags, inner: Lock::new(HandlerInner { flags, err_count: 0, deduplicated_err_count: 0, - emitter: e, + emitter, continue_after_error: true, delayed_span_bugs: Vec::new(), taught_diagnostics: Default::default(), @@ -474,7 +490,8 @@ impl Handler { "{}:{}: already existing stashed diagnostic with (span = {:?}, key = {:?})", file!(), line!(), span, key )); - inner.emit_explicit_bug(&old_diag); + inner.emit_diag_at_span(old_diag, span); + panic!(ExplicitBug); } } @@ -492,34 +509,35 @@ impl Handler { self.inner.borrow_mut().emit_stashed_diagnostics(); } + /// Construct a dummy builder with `Level::Cancelled`. + /// + /// Using this will neither report anything to the user (e.g. a warning), + /// nor will compilation cancel as a result. pub fn struct_dummy(&self) -> DiagnosticBuilder<'_> { DiagnosticBuilder::new(self, Level::Cancelled, "") } - pub fn struct_span_warn>(&self, - sp: S, - msg: &str) - -> DiagnosticBuilder<'_> { - let mut result = DiagnosticBuilder::new(self, Level::Warning, msg); - result.set_span(sp); - if !self.flags.can_emit_warnings { - result.cancel(); - } + /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. + pub fn struct_span_warn(&self, span: impl Into, msg: &str) -> DiagnosticBuilder<'_> { + let mut result = self.struct_warn(msg); + result.set_span(span); result } - pub fn struct_span_warn_with_code>(&self, - sp: S, - msg: &str, - code: DiagnosticId) - -> DiagnosticBuilder<'_> { - let mut result = DiagnosticBuilder::new(self, Level::Warning, msg); - result.set_span(sp); + + /// Construct a builder at the `Warning` level at the given `span` and with the `msg`. + /// Also include a code. + pub fn struct_span_warn_with_code( + &self, + span: impl Into, + msg: &str, + code: DiagnosticId, + ) -> DiagnosticBuilder<'_> { + let mut result = self.struct_span_warn(span, msg); result.code(code); - if !self.flags.can_emit_warnings { - result.cancel(); - } result } + + /// Construct a builder at the `Warning` level with the `msg`. pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> { let mut result = DiagnosticBuilder::new(self, Level::Warning, msg); if !self.flags.can_emit_warnings { @@ -527,136 +545,141 @@ impl Handler { } result } - pub fn struct_span_err>(&self, - sp: S, - msg: &str) - -> DiagnosticBuilder<'_> { - let mut result = DiagnosticBuilder::new(self, Level::Error, msg); - result.set_span(sp); + + /// Construct a builder at the `Error` level at the given `span` and with the `msg`. + pub fn struct_span_err(&self, span: impl Into, msg: &str) -> DiagnosticBuilder<'_> { + let mut result = self.struct_err(msg); + result.set_span(span); result } - pub fn struct_span_err_with_code>(&self, - sp: S, - msg: &str, - code: DiagnosticId) - -> DiagnosticBuilder<'_> { - let mut result = DiagnosticBuilder::new(self, Level::Error, msg); - result.set_span(sp); + + /// Construct a builder at the `Error` level at the given `span`, with the `msg`, and `code`. + pub fn struct_span_err_with_code( + &self, + span: impl Into, + msg: &str, + code: DiagnosticId, + ) -> DiagnosticBuilder<'_> { + let mut result = self.struct_span_err(span, msg); result.code(code); result } + + /// Construct a builder at the `Error` level with the `msg`. // FIXME: This method should be removed (every error should have an associated error code). pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_> { DiagnosticBuilder::new(self, Level::Error, msg) } - pub fn struct_err_with_code( - &self, - msg: &str, - code: DiagnosticId, - ) -> DiagnosticBuilder<'_> { - let mut result = DiagnosticBuilder::new(self, Level::Error, msg); + + /// Construct a builder at the `Error` level with the `msg` and the `code`. + pub fn struct_err_with_code(&self, msg: &str, code: DiagnosticId) -> DiagnosticBuilder<'_> { + let mut result = self.struct_err(msg); result.code(code); result } - pub fn struct_span_fatal>(&self, - sp: S, - msg: &str) - -> DiagnosticBuilder<'_> { - let mut result = DiagnosticBuilder::new(self, Level::Fatal, msg); - result.set_span(sp); + + /// Construct a builder at the `Fatal` level at the given `span` and with the `msg`. + pub fn struct_span_fatal( + &self, + span: impl Into, + msg: &str, + ) -> DiagnosticBuilder<'_> { + let mut result = self.struct_fatal(msg); + result.set_span(span); result } - pub fn struct_span_fatal_with_code>(&self, - sp: S, - msg: &str, - code: DiagnosticId) - -> DiagnosticBuilder<'_> { - let mut result = DiagnosticBuilder::new(self, Level::Fatal, msg); - result.set_span(sp); + + /// Construct a builder at the `Fatal` level at the given `span`, with the `msg`, and `code`. + pub fn struct_span_fatal_with_code( + &self, + span: impl Into, + msg: &str, + code: DiagnosticId, + ) -> DiagnosticBuilder<'_> { + let mut result = self.struct_span_fatal(span, msg); result.code(code); result } + + /// Construct a builder at the `Error` level with the `msg`. pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_> { DiagnosticBuilder::new(self, Level::Fatal, msg) } - pub fn span_fatal>(&self, sp: S, msg: &str) -> FatalError { - self.emit_diagnostic(Diagnostic::new(Fatal, msg).set_span(sp)); - self.abort_if_errors_and_should_abort(); + pub fn span_fatal(&self, span: impl Into, msg: &str) -> FatalError { + self.emit_diag_at_span(Diagnostic::new(Fatal, msg), span); FatalError } - pub fn span_fatal_with_code>(&self, - sp: S, - msg: &str, - code: DiagnosticId) - -> FatalError { - self.emit_diagnostic(Diagnostic::new_with_code(Fatal, Some(code), msg).set_span(sp)); - self.abort_if_errors_and_should_abort(); + + pub fn span_fatal_with_code( + &self, + span: impl Into, + msg: &str, + code: DiagnosticId, + ) -> FatalError { + self.emit_diag_at_span(Diagnostic::new_with_code(Fatal, Some(code), msg), span); FatalError } - pub fn span_err>(&self, sp: S, msg: &str) { - self.emit_diagnostic(Diagnostic::new(Error, msg).set_span(sp)); - self.abort_if_errors_and_should_abort(); - } - pub fn mut_span_err>(&self, - sp: S, - msg: &str) - -> DiagnosticBuilder<'_> { - let mut result = DiagnosticBuilder::new(self, Level::Error, msg); - result.set_span(sp); - result + + pub fn span_err(&self, span: impl Into, msg: &str) { + self.emit_diag_at_span(Diagnostic::new(Error, msg), span); } - pub fn span_err_with_code>(&self, sp: S, msg: &str, code: DiagnosticId) { - self.emit_diagnostic(Diagnostic::new_with_code(Error, Some(code), msg).set_span(sp)); - self.abort_if_errors_and_should_abort(); + + pub fn span_err_with_code(&self, span: impl Into, msg: &str, code: DiagnosticId) { + self.emit_diag_at_span(Diagnostic::new_with_code(Error, Some(code), msg), span); } - pub fn span_warn>(&self, sp: S, msg: &str) { - self.emit_diagnostic(Diagnostic::new(Warning, msg).set_span(sp)); - self.abort_if_errors_and_should_abort(); + + pub fn span_warn(&self, span: impl Into, msg: &str) { + self.emit_diag_at_span(Diagnostic::new(Warning, msg), span); } - pub fn span_warn_with_code>(&self, sp: S, msg: &str, code: DiagnosticId) { - self.emit_diagnostic(Diagnostic::new_with_code(Warning, Some(code), msg).set_span(sp)); - self.abort_if_errors_and_should_abort(); + + pub fn span_warn_with_code(&self, span: impl Into, msg: &str, code: DiagnosticId) { + self.emit_diag_at_span(Diagnostic::new_with_code(Warning, Some(code), msg), span); } - pub fn span_bug>(&self, sp: S, msg: &str) -> ! { - self.inner.borrow_mut().span_bug(sp, msg) + + pub fn span_bug(&self, span: impl Into, msg: &str) -> ! { + self.inner.borrow_mut().span_bug(span, msg) } - pub fn delay_span_bug>(&self, sp: S, msg: &str) { - self.inner.borrow_mut().delay_span_bug(sp, msg) + + pub fn delay_span_bug(&self, span: impl Into, msg: &str) { + self.inner.borrow_mut().delay_span_bug(span, msg) } - pub fn span_bug_no_panic>(&self, sp: S, msg: &str) { - self.emit_diagnostic(Diagnostic::new(Bug, msg).set_span(sp)); - self.abort_if_errors_and_should_abort(); + + pub fn span_bug_no_panic(&self, span: impl Into, msg: &str) { + self.emit_diag_at_span(Diagnostic::new(Bug, msg), span); } - pub fn span_note_without_error>(&self, sp: S, msg: &str) { - self.emit_diagnostic(Diagnostic::new(Note, msg).set_span(sp)); - self.abort_if_errors_and_should_abort(); + + pub fn span_note_without_error(&self, span: impl Into, msg: &str) { + self.emit_diag_at_span(Diagnostic::new(Note, msg), span); } - pub fn span_note_diag(&self, - sp: Span, - msg: &str) - -> DiagnosticBuilder<'_> { + + pub fn span_note_diag(&self, span: Span, msg: &str) -> DiagnosticBuilder<'_> { let mut db = DiagnosticBuilder::new(self, Note, msg); - db.set_span(sp); + db.set_span(span); db } + pub fn failure(&self, msg: &str) { self.inner.borrow_mut().failure(msg); } + pub fn fatal(&self, msg: &str) -> FatalError { self.inner.borrow_mut().fatal(msg) } + pub fn err(&self, msg: &str) { self.inner.borrow_mut().err(msg); } + pub fn warn(&self, msg: &str) { let mut db = DiagnosticBuilder::new(self, Warning, msg); db.emit(); } + pub fn note_without_error(&self, msg: &str) { - let mut db = DiagnosticBuilder::new(self, Note, msg); - db.emit(); + DiagnosticBuilder::new(self, Note, msg).emit(); } + pub fn bug(&self, msg: &str) -> ! { self.inner.borrow_mut().bug(msg) } @@ -698,6 +721,12 @@ impl Handler { self.inner.borrow_mut().emit_diagnostic(diagnostic) } + fn emit_diag_at_span(&self, mut diag: Diagnostic, sp: impl Into) { + let mut inner = self.inner.borrow_mut(); + inner.emit_diagnostic(diag.set_span(sp)); + inner.abort_if_errors_and_should_abort(); + } + pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { self.inner.borrow_mut().emit_artifact_notification(path, artifact_type) } @@ -837,17 +866,17 @@ impl HandlerInner { } } - fn span_bug>(&mut self, sp: S, msg: &str) -> ! { - self.emit_explicit_bug(Diagnostic::new(Bug, msg).set_span(sp)); + fn span_bug(&mut self, sp: impl Into, msg: &str) -> ! { + self.emit_diag_at_span(Diagnostic::new(Bug, msg), sp); + panic!(ExplicitBug); } - fn emit_explicit_bug(&mut self, diag: &Diagnostic) -> ! { - self.emit_diagnostic(diag); + fn emit_diag_at_span(&mut self, mut diag: Diagnostic, sp: impl Into) { + self.emit_diagnostic(diag.set_span(sp)); self.abort_if_errors_and_should_abort(); - panic!(ExplicitBug); } - fn delay_span_bug>(&mut self, sp: S, msg: &str) { + fn delay_span_bug(&mut self, sp: impl Into, msg: &str) { if self.treat_err_as_bug() { // FIXME: don't abort here if report_delayed_bugs is off self.span_bug(sp, msg); @@ -862,18 +891,20 @@ impl HandlerInner { } fn fatal(&mut self, msg: &str) -> FatalError { - if self.treat_err_as_bug() { - self.bug(msg); - } - self.emit_diagnostic(&Diagnostic::new(Fatal, msg)); + self.emit_error(Fatal, msg); FatalError } fn err(&mut self, msg: &str) { + self.emit_error(Error, msg); + } + + /// Emit an error; level should be `Error` or `Fatal`. + fn emit_error(&mut self, level: Level, msg: &str,) { if self.treat_err_as_bug() { self.bug(msg); } - self.emit_diagnostic(&Diagnostic::new(Error, msg)); + self.emit_diagnostic(&Diagnostic::new(level, msg)); } fn bug(&mut self, msg: &str) -> ! { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index b0e886a2aa2eb..f7e766bb84d57 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -832,7 +832,7 @@ fn check_method_receiver<'fcx, 'tcx>( } fn e0307(fcx: &FnCtxt<'fcx, 'tcx>, span: Span, receiver_ty: Ty<'_>) { - fcx.tcx.sess.diagnostic().mut_span_err( + fcx.tcx.sess.diagnostic().struct_span_err( span, &format!("invalid `self` parameter type: {:?}", receiver_ty) ).note("type of `self` must be `Self` or a type that dereferences to it") diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index a6be5b101788e..36d066b026933 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -1041,10 +1041,6 @@ impl<'a> ExtCtxt<'a> { pub fn span_err_with_code>(&self, sp: S, msg: &str, code: DiagnosticId) { self.parse_sess.span_diagnostic.span_err_with_code(sp, msg, code); } - pub fn mut_span_err>(&self, sp: S, msg: &str) - -> DiagnosticBuilder<'a> { - self.parse_sess.span_diagnostic.mut_span_err(sp, msg) - } pub fn span_warn>(&self, sp: S, msg: &str) { self.parse_sess.span_diagnostic.span_warn(sp, msg); } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index b80c530731dfc..c3b1f91d5317d 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -384,7 +384,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let attr = attr::find_by_name(item.attrs(), sym::derive) .expect("`derive` attribute should exist"); let span = attr.span; - let mut err = self.cx.mut_span_err(span, + let mut err = self.cx.struct_span_err(span, "`derive` may only be applied to structs, enums and unions"); if let ast::AttrStyle::Inner = attr.style { let trait_list = derives.iter() diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 26455df17b896..2765346b333cf 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -295,7 +295,7 @@ impl<'a, 'b> Context<'a, 'b> { .filter(|fmt| fmt.precision_span.is_some()) .count(); if self.names.is_empty() && !numbered_position_args && count != self.args.len() { - e = self.ecx.mut_span_err( + e = self.ecx.struct_span_err( sp, &format!( "{} positional argument{} in format string, but {}", @@ -336,7 +336,7 @@ impl<'a, 'b> Context<'a, 'b> { sp = MultiSpan::from_span(self.fmtsp); } - e = self.ecx.mut_span_err(sp, + e = self.ecx.struct_span_err(sp, &format!("invalid reference to positional {} ({})", arg_list, self.describe_num_args())); From f00c6346b42d2a3091752166cd86aa2d69112dcc Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 23 Sep 2019 14:01:06 -0700 Subject: [PATCH 130/413] Allow using upstream generics in a dylib crate type ... just don't export them! --- src/librustc_codegen_ssa/back/linker.rs | 22 ++++++++++++++++++++-- src/librustc_metadata/cstore_impl.rs | 13 ++++++------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index 940a9a72bf6d4..ff87f0b1547ce 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -14,6 +14,7 @@ use rustc::middle::dependency_format::Linkage; use rustc::session::Session; use rustc::session::config::{self, CrateType, OptLevel, DebugInfo, LinkerPluginLto, Lto}; +use rustc::middle::exported_symbols::ExportedSymbol; use rustc::ty::TyCtxt; use rustc_target::spec::{LinkerFlavor, LldFlavor}; use rustc_serialize::{json, Encoder}; @@ -1107,9 +1108,26 @@ fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec { if *dep_format == Linkage::Static { // ... we add its symbol list to our export list. for &(symbol, level) in tcx.exported_symbols(cnum).iter() { - if level.is_below_threshold(export_threshold) { - symbols.push(symbol.symbol_name(tcx).to_string()); + if !level.is_below_threshold(export_threshold) { + continue; } + + // Do not export generic symbols from upstream crates in linked + // artifact (notably the `dylib` crate type). The main reason + // for this is that `symbol_name` is actually wrong for generic + // symbols because it guesses the name we'd give them locally + // rather than the name it has upstream (depending on + // `share_generics` settings and such). + // + // To fix that issue we just say that linked artifacts, aka + // `dylib`s, never export generic symbols and they aren't + // available to downstream crates. (the not available part is + // handled elsewhere). + if let ExportedSymbol::Generic(..) = symbol { + continue; + } + + symbols.push(symbol.symbol_name(tcx).to_string()); } } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index f18a98ffea7cd..0bc53dbde5f8a 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -11,7 +11,6 @@ use rustc::middle::cstore::{CrateStore, DepKind, use rustc::middle::exported_symbols::ExportedSymbol; use rustc::middle::stability::DeprecationEntry; use rustc::middle::dependency_format::Linkage; -use rustc::session::config::CrateType; use rustc::hir::def; use rustc::hir; use rustc::session::{CrateDisambiguator, Session}; @@ -246,13 +245,13 @@ provide! { <'tcx> tcx, def_id, other, cdata, // When linked into a dylib crates don't export their generic symbols, // so if that's happening then we can't load upstream monomorphizations - // from this crate. As a result, if we're creating a dylib or this crate - // is being included from a different dynamic library, then we filter - // out all `Generic` symbols here. + // from this crate. let formats = tcx.dependency_formats(LOCAL_CRATE); - let remove_generics = formats.iter().any(|(ty, list)| { - *ty == CrateType::Dylib || - list.get(def_id.krate.as_usize() - 1) == Some(&Linkage::IncludedFromDylib) + let remove_generics = formats.iter().any(|(_ty, list)| { + match list.get(def_id.krate.as_usize() - 1) { + Some(Linkage::IncludedFromDylib) | Some(Linkage::Dynamic) => true, + _ => false, + } }); if remove_generics { syms.retain(|(sym, _threshold)| { From 4fd9b9944f52afa948288c96c9860709c9f82231 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 18 Sep 2019 14:35:56 -0700 Subject: [PATCH 131/413] Add cycle detection for graphs --- .../graph/iterate/mod.rs | 204 +++++++++++++++++- .../graph/iterate/tests.rs | 11 + src/librustc_data_structures/graph/mod.rs | 10 + 3 files changed, 224 insertions(+), 1 deletion(-) diff --git a/src/librustc_data_structures/graph/iterate/mod.rs b/src/librustc_data_structures/graph/iterate/mod.rs index c4185fc7cd9c3..cbf6a0a3c03a0 100644 --- a/src/librustc_data_structures/graph/iterate/mod.rs +++ b/src/librustc_data_structures/graph/iterate/mod.rs @@ -1,5 +1,5 @@ use super::super::indexed_vec::IndexVec; -use super::{DirectedGraph, WithNumNodes, WithSuccessors}; +use super::{DirectedGraph, WithNumNodes, WithSuccessors, WithStartNode}; use crate::bit_set::BitSet; #[cfg(test)] @@ -85,3 +85,205 @@ where Some(n) } } + +/// Allows searches to terminate early with a value. +#[derive(Clone, Copy, Debug)] +pub enum ControlFlow { + Break(T), + Continue, +} + +/// The status of a node in the depth-first search. +/// +/// See the documentation of `TriColorDepthFirstSearch` to see how a node's status is updated +/// during DFS. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum NodeStatus { + /// This node has been examined by the depth-first search but is not yet `Settled`. + /// + /// Also referred to as "gray" or "discovered" nodes in [CLR][]. + /// + /// [CLR]: https://en.wikipedia.org/wiki/Introduction_to_Algorithms + Visited, + + /// This node and all nodes reachable from it have been examined by the depth-first search. + /// + /// Also referred to as "black" or "finished" nodes in [CLR][]. + /// + /// [CLR]: https://en.wikipedia.org/wiki/Introduction_to_Algorithms + Settled, +} + +struct Event { + node: N, + becomes: NodeStatus, +} + +/// A depth-first search that also tracks when all successors of a node have been examined. +/// +/// This is based on the DFS described in [Introduction to Algorithms (1st ed.)][CLR], hereby +/// referred to as **CLR**. However, we use the terminology in [`NodeStatus`][] above instead of +/// "discovered"/"finished" or "white"/"grey"/"black". Each node begins the search with no status, +/// becomes `Visited` when it is first examined by the DFS and is `Settled` when all nodes +/// reachable from it have been examined. This allows us to differentiate between "tree", "back" +/// and "forward" edges (see [`TriColorVisitor::node_examined`]). +/// +/// Unlike the pseudocode in [CLR][], this implementation is iterative and does not use timestamps. +/// We accomplish this by storing `Event`s on the stack that result in a (possible) state change +/// for each node. A `Visited` event signifies that we should examine this node if it has not yet +/// been `Visited` or `Settled`. When a node is examined for the first time, we mark it as +/// `Visited` and push a `Settled` event for it on stack followed by `Visited` events for all of +/// its predecessors, scheduling them for examination. Multiple `Visited` events for a single node +/// may exist on the stack simultaneously if a node has multiple predecessors, but only one +/// `Settled` event will ever be created for each node. After all `Visited` events for a node's +/// successors have been popped off the stack (as well as any new events triggered by visiting +/// those successors), we will pop off that node's `Settled` event. +/// +/// [CLR]: https://en.wikipedia.org/wiki/Introduction_to_Algorithms +/// [`NodeStatus`]: ./enum.NodeStatus.html +/// [`TriColorVisitor::node_examined`]: ./trait.TriColorVisitor.html#method.node_examined +pub struct TriColorDepthFirstSearch<'graph, G> +where + G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors, +{ + graph: &'graph G, + stack: Vec>, + visited: BitSet, + settled: BitSet, +} + +impl TriColorDepthFirstSearch<'graph, G> +where + G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors, +{ + pub fn new(graph: &'graph G) -> Self { + TriColorDepthFirstSearch { + graph, + stack: vec![], + visited: BitSet::new_empty(graph.num_nodes()), + settled: BitSet::new_empty(graph.num_nodes()), + } + } + + /// Performs a depth-first search, starting from the given `root`. + /// + /// This won't visit nodes that are not reachable from `root`. + pub fn run_from(mut self, root: G::Node, visitor: &mut V) -> Option + where + V: TriColorVisitor, + { + use NodeStatus::{Visited, Settled}; + + self.stack.push(Event { node: root, becomes: Visited }); + + loop { + match self.stack.pop()? { + Event { node, becomes: Settled } => { + let not_previously_settled = self.settled.insert(node); + assert!(not_previously_settled, "A node should be settled exactly once"); + if let ControlFlow::Break(val) = visitor.node_settled(node) { + return Some(val); + } + } + + Event { node, becomes: Visited } => { + let not_previously_visited = self.visited.insert(node); + let prior_status = if not_previously_visited { + None + } else if self.settled.contains(node) { + Some(Settled) + } else { + Some(Visited) + }; + + if let ControlFlow::Break(val) = visitor.node_examined(node, prior_status) { + return Some(val); + } + + // If this node has already been examined, we are done. + if prior_status.is_some() { + continue; + } + + // Otherwise, push a `Settled` event for this node onto the stack, then + // schedule its successors for examination. + self.stack.push(Event { node, becomes: Settled }); + for succ in self.graph.successors(node) { + self.stack.push(Event { node: succ, becomes: Visited }); + } + } + } + } + } +} + +impl TriColorDepthFirstSearch<'graph, G> +where + G: ?Sized + DirectedGraph + WithNumNodes + WithSuccessors + WithStartNode, +{ + /// Performs a depth-first search, starting from `G::start_node()`. + /// + /// This won't visit nodes that are not reachable from the start node. + pub fn run_from_start(self, visitor: &mut V) -> Option + where + V: TriColorVisitor, + { + let root = self.graph.start_node(); + self.run_from(root, visitor) + } +} + +/// What to do when a node is examined or becomes `Settled` during DFS. +pub trait TriColorVisitor +where + G: ?Sized + DirectedGraph, +{ + /// The value returned by this search. + type BreakVal; + + /// Called when a node is examined by the depth-first search. + /// + /// By checking the value of `prior_status`, this visitor can determine whether the edge + /// leading to this node was a tree edge (`None`), forward edge (`Some(Settled)`) or back edge + /// (`Some(Visited)`). For a full explanation of each edge type, see the "Depth-first Search" + /// chapter in [CLR][] or [wikipedia][]. + /// + /// If you want to know *both* nodes linked by each edge, you'll need to modify + /// `TriColorDepthFirstSearch` to store a `source` node for each `Visited` event. + /// + /// [wikipedia]: https://en.wikipedia.org/wiki/Depth-first_search#Output_of_a_depth-first_search + /// [CLR]: https://en.wikipedia.org/wiki/Introduction_to_Algorithms + fn node_examined( + &mut self, + _target: G::Node, + _prior_status: Option, + ) -> ControlFlow { + ControlFlow::Continue + } + + /// Called after all nodes reachable from this one have been examined. + fn node_settled(&mut self, _target: G::Node) -> ControlFlow { + ControlFlow::Continue + } +} + +/// This `TriColorVisitor` looks for back edges in a graph, which indicate that a cycle exists. +pub struct CycleDetector; + +impl TriColorVisitor for CycleDetector +where + G: ?Sized + DirectedGraph, +{ + type BreakVal = (); + + fn node_examined( + &mut self, + _node: G::Node, + prior_status: Option, + ) -> ControlFlow { + match prior_status { + Some(NodeStatus::Visited) => ControlFlow::Break(()), + _ => ControlFlow::Continue, + } + } +} diff --git a/src/librustc_data_structures/graph/iterate/tests.rs b/src/librustc_data_structures/graph/iterate/tests.rs index 6c7cfd6d8a777..0e038e88b221d 100644 --- a/src/librustc_data_structures/graph/iterate/tests.rs +++ b/src/librustc_data_structures/graph/iterate/tests.rs @@ -9,3 +9,14 @@ fn diamond_post_order() { let result = post_order_from(&graph, 0); assert_eq!(result, vec![3, 1, 2, 0]); } + +#[test] +fn is_cyclic() { + use super::super::is_cyclic; + + let diamond_acyclic = TestGraph::new(0, &[(0, 1), (0, 2), (1, 3), (2, 3)]); + let diamond_cyclic = TestGraph::new(0, &[(0, 1), (1, 2), (2, 3), (3, 0)]); + + assert!(!is_cyclic(&diamond_acyclic)); + assert!(is_cyclic(&diamond_cyclic)); +} diff --git a/src/librustc_data_structures/graph/mod.rs b/src/librustc_data_structures/graph/mod.rs index 662581ca1e498..0a607659f3e24 100644 --- a/src/librustc_data_structures/graph/mod.rs +++ b/src/librustc_data_structures/graph/mod.rs @@ -81,3 +81,13 @@ where + WithNumNodes, { } + +/// Returns `true` if the graph has a cycle that is reachable from the start node. +pub fn is_cyclic(graph: &G) -> bool +where + G: ?Sized + DirectedGraph + WithStartNode + WithSuccessors + WithNumNodes, +{ + iterate::TriColorDepthFirstSearch::new(graph) + .run_from_start(&mut iterate::CycleDetector) + .is_some() +} From c9e4816fe319b2fde83779ff375037c8079d36a2 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 18 Sep 2019 14:53:55 -0700 Subject: [PATCH 132/413] Add convenience function for detecting cyclic CFGs --- src/librustc/mir/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 0ebc70750a6bb..5206e044f9fa5 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -262,6 +262,12 @@ impl<'tcx> Body<'tcx> { dominators(self) } + /// Returns `true` if a cycle exists in the control-flow graph that is reachable from the + /// `START_BLOCK`. + pub fn is_cfg_cyclic(&self) -> bool { + graph::is_cyclic(self) + } + #[inline] pub fn local_kind(&self, local: Local) -> LocalKind { let index = local.as_usize(); From fa2cfaf064ecda727fb922864a8eafbae1875228 Mon Sep 17 00:00:00 2001 From: hman523 Date: Mon, 23 Sep 2019 18:20:21 -0500 Subject: [PATCH 133/413] Fixed issue from #64447 --- src/librustc_errors/emitter.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index fc441320e0039..c13a4b8dbb487 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -1043,14 +1043,13 @@ impl EmitterWriter { } fn get_max_line_num(&mut self, span: &MultiSpan, children: &[SubDiagnostic]) -> usize { - let mut max = 0; let primary = self.get_multispan_max_line_num(span); - max = if primary > max { primary } else { max }; + let mut max = primary; for sub in children { let sub_result = self.get_multispan_max_line_num(&sub.span); - max = if sub_result > max { primary } else { max }; + max = if sub_result > max { sub_result } else { max }; } max } From a6da0e921b01352dbdf45320afc9e41f27ac5784 Mon Sep 17 00:00:00 2001 From: hman523 Date: Mon, 23 Sep 2019 19:51:15 -0500 Subject: [PATCH 134/413] changed a line from an if else to std::cmp::max --- src/librustc_errors/emitter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index c13a4b8dbb487..2a89c94652a24 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -1049,7 +1049,7 @@ impl EmitterWriter { for sub in children { let sub_result = self.get_multispan_max_line_num(&sub.span); - max = if sub_result > max { sub_result } else { max }; + max = std::cmp::max(sub_result, max); } max } From 5aa5d5780839cda5a7fde2cf434a630b98cd485b Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Tue, 24 Sep 2019 10:29:09 +0800 Subject: [PATCH 135/413] fix one typo --- src/librustc_typeck/check/method/suggest.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 74e4f28255b16..4c681544978e5 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -232,7 +232,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let mut err = if !actual.references_error() { // Suggest clamping down the type if the method that is being attempted to - // be used exists at all, and the type is an ambiuous numeric type + // be used exists at all, and the type is an ambiguous numeric type // ({integer}/{float}). let mut candidates = all_traits(self.tcx) .into_iter() From 6ac64abd6d4fdd60c6ee34fb1a14d2eaa9faed16 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sun, 22 Sep 2019 21:14:54 -0700 Subject: [PATCH 136/413] Just delete the overrides now that they match the default implementations --- src/libcore/slice/mod.rs | 63 +--------------------------------------- 1 file changed, 1 insertion(+), 62 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 59f95cff5aee1..ccdab1dcf0dc9 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -28,7 +28,7 @@ use crate::fmt; use crate::intrinsics::{assume, exact_div, unchecked_sub, is_aligned_and_not_null}; use crate::isize; use crate::iter::*; -use crate::ops::{FnMut, Try, self}; +use crate::ops::{FnMut, self}; use crate::option::Option; use crate::option::Option::{None, Some}; use crate::result::Result; @@ -3180,33 +3180,6 @@ macro_rules! iterator { self.next_back() } - #[inline] - fn try_fold(&mut self, init: B, mut f: F) -> R where - Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try - { - // This method historically was unrolled, for as of 2019-09 LLVM - // is not capable of unrolling or vectorizing multiple-exit loops. - // However, doing it always proved to often be a pessimization, - // especially when called with large closures, so it was removed. - - let mut accum = init; - while let Some(x) = self.next() { - accum = f(accum, x)?; - } - Try::from_ok(accum) - } - - #[inline] - fn fold(mut self, init: Acc, mut f: Fold) -> Acc - where Fold: FnMut(Acc, Self::Item) -> Acc, - { - let mut accum = init; - while let Some(x) = self.next() { - accum = f(accum, x); - } - accum - } - #[inline] #[rustc_inherit_overflow_checks] fn position

    (&mut self, mut predicate: P) -> Option where @@ -3277,40 +3250,6 @@ macro_rules! iterator { Some(next_back_unchecked!(self)) } } - - #[inline] - fn try_rfold(&mut self, init: B, mut f: F) -> R where - Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try - { - // manual unrolling is needed when there are conditional exits from the loop - let mut accum = init; - unsafe { - while len!(self) >= 4 { - accum = f(accum, next_back_unchecked!(self))?; - accum = f(accum, next_back_unchecked!(self))?; - accum = f(accum, next_back_unchecked!(self))?; - accum = f(accum, next_back_unchecked!(self))?; - } - // inlining is_empty everywhere makes a huge performance difference - while !is_empty!(self) { - accum = f(accum, next_back_unchecked!(self))?; - } - } - Try::from_ok(accum) - } - - #[inline] - fn rfold(mut self, init: Acc, mut f: Fold) -> Acc - where Fold: FnMut(Acc, Self::Item) -> Acc, - { - // Let LLVM unroll this, rather than using the default - // impl that would force the manual unrolling above - let mut accum = init; - while let Some(x) = self.next_back() { - accum = f(accum, x); - } - accum - } } #[stable(feature = "fused", since = "1.26.0")] From a744fd04321f6307303a22ecc8880cbc7b6bcbda Mon Sep 17 00:00:00 2001 From: csmoe Date: Mon, 23 Sep 2019 17:13:11 +0000 Subject: [PATCH 137/413] bug-out asyncness query on non-local funtions --- src/librustc/ty/mod.rs | 21 +++++++++++---------- src/librustc_metadata/decoder.rs | 3 ++- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index dd36a4520929a..98fa64c265cb2 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3351,16 +3351,17 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { /// Check if a function is async. fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync { - if let Some(hir_id) = tcx.hir().as_local_hir_id(def_id) { - let node = tcx.hir().get(hir_id); - if let Some(fn_like) = hir::map::blocks::FnLikeNode::from_node(node) { - fn_like.asyncness() - } else { - hir::IsAsync::NotAsync - } - } else { - hir::IsAsync::NotAsync - } + let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap_or_else(|| { + bug!("asyncness: expected local `DefId`, got `{:?}`", def_id) + }); + + let node = tcx.hir().get(hir_id); + + let fn_like = hir::map::blocks::FnLikeNode::from_node(node).unwrap_or_else(|| { + bug!("asyncness: expected fn-like node but got `{:?}`", def_id); + }); + + fn_like.asyncness() } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 5153564fc8255..6698c7cb17036 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1212,7 +1212,8 @@ impl<'a, 'tcx> CrateMetadata { match self.entry(id).kind { EntryKind::Fn(data) => data.decode(self).asyncness, EntryKind::Method(data) => data.decode(self).fn_data.asyncness, - _ => hir::IsAsync::NotAsync, + EntryKind::ForeignFn(data) => data.decode(self).asyncness, + _ => bug!("asyncness: expect functions entry."), } } From 7767e7fb165d527f1991175809a361f2d2313b80 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 21 Aug 2019 02:23:46 +0200 Subject: [PATCH 138/413] Stabilize `str::len`, `[T]::len`, `is_empty` and `str::as_bytes` as const fn --- src/libcore/lib.rs | 6 +- src/libcore/slice/mod.rs | 6 +- src/libcore/str/mod.rs | 8 +- src/librustc_mir/transform/check_unsafety.rs | 4 +- .../transform/qualify_min_const_fn.rs | 81 +++++++++++++------ src/libsyntax/attr/mod.rs | 24 ++++++ src/libsyntax/ext/base.rs | 30 +------ src/test/ui/consts/const-eval/strlen.rs | 12 ++- .../min_const_fn/min_const_fn_unsafe_bad.rs | 2 +- .../min_const_fn_unsafe_bad.stderr | 8 +- src/test/ui/issues/issue-52060.rs | 1 - src/test/ui/issues/issue-52060.stderr | 10 +-- 12 files changed, 114 insertions(+), 78 deletions(-) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 5c681b3a5d807..8221df56a5142 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -120,9 +120,9 @@ #![feature(rtm_target_feature)] #![feature(f16c_target_feature)] #![feature(hexagon_target_feature)] -#![feature(const_slice_len)] -#![feature(const_str_as_bytes)] -#![feature(const_str_len)] +#![cfg_attr(bootstrap, feature(const_slice_len))] +#![cfg_attr(bootstrap, feature(const_str_as_bytes))] +#![cfg_attr(bootstrap, feature(const_str_len))] #![feature(const_int_conversion)] #![feature(const_transmute)] #![feature(non_exhaustive)] diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 931768564ca3c..0c2a4e086727b 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -62,7 +62,9 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - #[rustc_const_unstable(feature = "const_slice_len")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_slice_len"))] + // SAFETY: const sound because we transmute out the length field as a usize (which it must be) + #[cfg_attr(not(bootstrap), allow_internal_unstable(const_fn_union))] pub const fn len(&self) -> usize { unsafe { crate::ptr::Repr { rust: self }.raw.len @@ -79,7 +81,7 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - #[rustc_const_unstable(feature = "const_slice_len")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_slice_len"))] pub const fn is_empty(&self) -> bool { self.len() == 0 } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 5e5b5593fd8a7..a6ec757faf1d6 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2090,7 +2090,7 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - #[rustc_const_unstable(feature = "const_str_len")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_str_len"))] pub const fn len(&self) -> usize { self.as_bytes().len() } @@ -2110,7 +2110,7 @@ impl str { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable(feature = "const_str_len")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_str_len"))] pub const fn is_empty(&self) -> bool { self.len() == 0 } @@ -2168,7 +2168,9 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline(always)] - #[rustc_const_unstable(feature="const_str_as_bytes")] + #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_str_as_bytes"))] + // SAFETY: const sound because we transmute two types with the same layout + #[cfg_attr(not(bootstrap), allow_internal_unstable(const_fn_union))] pub const fn as_bytes(&self) -> &[u8] { #[repr(C)] union Slices<'a> { diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 39aa5c717acc1..61e32ca8de522 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -305,7 +305,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { "assignment to non-`Copy` union field", "the previous content of the field will be dropped, which \ causes undefined behavior if the field was not properly \ - initialized", UnsafetyViolationKind::General) + initialized", UnsafetyViolationKind::GeneralAndConstFn) } else { // write to non-move union, safe } @@ -313,7 +313,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { self.require_unsafe("access to union field", "the field may not be properly initialized: using \ uninitialized data will cause undefined behavior", - UnsafetyViolationKind::General) + UnsafetyViolationKind::GeneralAndConstFn) } } } diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 80e020a9eb7e6..be83c823d4242 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -5,6 +5,8 @@ use rustc::ty::{self, Predicate, Ty, TyCtxt, adjustment::{PointerCast}}; use rustc_target::spec::abi; use std::borrow::Cow; use syntax_pos::Span; +use syntax::symbol::{sym, Symbol}; +use syntax::attr; type McfResult = Result<(), (Span, Cow<'static, str>)>; @@ -67,9 +69,9 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) - )?; for bb in body.basic_blocks() { - check_terminator(tcx, body, bb.terminator())?; + check_terminator(tcx, body, def_id, bb.terminator())?; for stmt in &bb.statements { - check_statement(tcx, body, stmt)?; + check_statement(tcx, body, def_id, stmt)?; } } Ok(()) @@ -121,16 +123,17 @@ fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> Mc fn check_rvalue( tcx: TyCtxt<'tcx>, - body: &'a Body<'tcx>, + body: &Body<'tcx>, + def_id: DefId, rvalue: &Rvalue<'tcx>, span: Span, ) -> McfResult { match rvalue { Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => { - check_operand(operand, span) + check_operand(tcx, operand, span, def_id, body) } Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) => { - check_place(place, span) + check_place(tcx, place, span, def_id, body) } Rvalue::Cast(CastKind::Misc, operand, cast_ty) => { use rustc::ty::cast::CastTy; @@ -144,11 +147,11 @@ fn check_rvalue( (CastTy::RPtr(_), CastTy::Float) => bug!(), (CastTy::RPtr(_), CastTy::Int(_)) => bug!(), (CastTy::Ptr(_), CastTy::RPtr(_)) => bug!(), - _ => check_operand(operand, span), + _ => check_operand(tcx, operand, span, def_id, body), } } Rvalue::Cast(CastKind::Pointer(PointerCast::MutToConstPointer), operand, _) => { - check_operand(operand, span) + check_operand(tcx, operand, span, def_id, body) } Rvalue::Cast(CastKind::Pointer(PointerCast::UnsafeFnPointer), _, _) | Rvalue::Cast(CastKind::Pointer(PointerCast::ClosureFnPointer(_)), _, _) | @@ -162,8 +165,8 @@ fn check_rvalue( )), // binops are fine on integers Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => { - check_operand(lhs, span)?; - check_operand(rhs, span)?; + check_operand(tcx, lhs, span, def_id, body)?; + check_operand(tcx, rhs, span, def_id, body)?; let ty = lhs.ty(body, tcx); if ty.is_integral() || ty.is_bool() || ty.is_char() { Ok(()) @@ -182,7 +185,7 @@ fn check_rvalue( Rvalue::UnaryOp(_, operand) => { let ty = operand.ty(body, tcx); if ty.is_integral() || ty.is_bool() { - check_operand(operand, span) + check_operand(tcx, operand, span, def_id, body) } else { Err(( span, @@ -192,7 +195,7 @@ fn check_rvalue( } Rvalue::Aggregate(_, operands) => { for operand in operands { - check_operand(operand, span)?; + check_operand(tcx, operand, span, def_id, body)?; } Ok(()) } @@ -201,21 +204,22 @@ fn check_rvalue( fn check_statement( tcx: TyCtxt<'tcx>, - body: &'a Body<'tcx>, + body: &Body<'tcx>, + def_id: DefId, statement: &Statement<'tcx>, ) -> McfResult { let span = statement.source_info.span; match &statement.kind { StatementKind::Assign(box(place, rval)) => { - check_place(place, span)?; - check_rvalue(tcx, body, rval, span) + check_place(tcx, place, span, def_id, body)?; + check_rvalue(tcx, body, def_id, rval, span) } StatementKind::FakeRead(FakeReadCause::ForMatchedPlace, _) => { Err((span, "loops and conditional expressions are not stable in const fn".into())) } - StatementKind::FakeRead(_, place) => check_place(place, span), + StatementKind::FakeRead(_, place) => check_place(tcx, place, span, def_id, body), // just an assignment StatementKind::SetDiscriminant { .. } => Ok(()), @@ -234,30 +238,48 @@ fn check_statement( } fn check_operand( + tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, + def_id: DefId, + body: &Body<'tcx> ) -> McfResult { match operand { Operand::Move(place) | Operand::Copy(place) => { - check_place(place, span) + check_place(tcx, place, span, def_id, body) } Operand::Constant(_) => Ok(()), } } fn check_place( + tcx: TyCtxt<'tcx>, place: &Place<'tcx>, span: Span, + def_id: DefId, + body: &Body<'tcx> ) -> McfResult { - for elem in place.projection.iter() { + let mut cursor = &*place.projection; + while let [proj_base @ .., elem] = cursor { + cursor = proj_base; match elem { ProjectionElem::Downcast(..) => { return Err((span, "`match` or `if let` in `const fn` is unstable".into())); } + ProjectionElem::Field(..) => { + let base_ty = Place::ty_from(&place.base, &proj_base, body, tcx).ty; + if let Some(def) = base_ty.ty_adt_def() { + // No union field accesses in `const fn` + if def.is_union() { + if !feature_allowed(tcx, def_id, sym::const_fn_union) { + return Err((span, "accessing union fields is unstable".into())); + } + } + } + } ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } | ProjectionElem::Deref - | ProjectionElem::Field(..) | ProjectionElem::Index(_) => {} } } @@ -271,9 +293,20 @@ fn check_place( } } +/// Returns whether `allow_internal_unstable(..., , ...)` is present. +fn feature_allowed( + tcx: TyCtxt<'tcx>, + def_id: DefId, + feature_gate: Symbol, +) -> bool { + attr::allow_internal_unstable(&tcx.get_attrs(def_id), &tcx.sess.diagnostic()) + .map_or(false, |mut features| features.any(|name| name == feature_gate)) +} + fn check_terminator( tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, + def_id: DefId, terminator: &Terminator<'tcx>, ) -> McfResult { let span = terminator.source_info.span; @@ -283,11 +316,11 @@ fn check_terminator( | TerminatorKind::Resume => Ok(()), TerminatorKind::Drop { location, .. } => { - check_place(location, span) + check_place(tcx, location, span, def_id, body) } TerminatorKind::DropAndReplace { location, value, .. } => { - check_place(location, span)?; - check_operand(value, span) + check_place(tcx, location, span, def_id, body)?; + check_operand(tcx, value, span, def_id, body) }, TerminatorKind::FalseEdges { .. } | TerminatorKind::SwitchInt { .. } => Err(( @@ -339,10 +372,10 @@ fn check_terminator( )), } - check_operand(func, span)?; + check_operand(tcx, func, span, def_id, body)?; for arg in args { - check_operand(arg, span)?; + check_operand(tcx, arg, span, def_id, body)?; } Ok(()) } else { @@ -356,7 +389,7 @@ fn check_terminator( msg: _, target: _, cleanup: _, - } => check_operand(cond, span), + } => check_operand(tcx, cond, span, def_id, body), TerminatorKind::FalseUnwind { .. } => { Err((span, "loops are not allowed in const fn".into())) diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 1f954064944dc..9d06b926f972e 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -433,6 +433,30 @@ pub fn find_by_name(attrs: &[Attribute], name: Symbol) -> Option<&Attribute> { attrs.iter().find(|attr| attr.check_name(name)) } +pub fn allow_internal_unstable<'a>( + attrs: &[Attribute], + span_diagnostic: &'a errors::Handler, +) -> Option + 'a> { + find_by_name(attrs, sym::allow_internal_unstable).and_then(|attr| { + attr.meta_item_list().or_else(|| { + span_diagnostic.span_err( + attr.span, + "allow_internal_unstable expects list of feature names" + ); + None + }).map(|features| features.into_iter().filter_map(move |it| { + let name = it.ident().map(|ident| ident.name); + if name.is_none() { + span_diagnostic.span_err( + it.span(), + "`allow_internal_unstable` expects feature names", + ) + } + name + })) + }) +} + pub fn filter_by_name(attrs: &[Attribute], name: Symbol) -> impl Iterator { attrs.iter().filter(move |attr| attr.check_name(name)) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index a6be5b101788e..e189d8f86362e 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -762,33 +762,9 @@ impl SyntaxExtension { name: Name, attrs: &[ast::Attribute], ) -> SyntaxExtension { - let allow_internal_unstable = - attr::find_by_name(attrs, sym::allow_internal_unstable).map(|attr| { - attr.meta_item_list() - .map(|list| { - list.iter() - .filter_map(|it| { - let name = it.ident().map(|ident| ident.name); - if name.is_none() { - sess.span_diagnostic.span_err( - it.span(), "allow internal unstable expects feature names" - ) - } - name - }) - .collect::>() - .into() - }) - .unwrap_or_else(|| { - sess.span_diagnostic.span_warn( - attr.span, - "allow_internal_unstable expects list of feature names. In the future \ - this will become a hard error. Please use `allow_internal_unstable(\ - foo, bar)` to only allow the `foo` and `bar` features", - ); - vec![sym::allow_internal_unstable_backcompat_hack].into() - }) - }); + let allow_internal_unstable = attr::allow_internal_unstable( + &attrs, &sess.span_diagnostic, + ).map(|features| features.collect::>().into()); let mut local_inner_macros = false; if let Some(macro_export) = attr::find_by_name(attrs, sym::macro_export) { diff --git a/src/test/ui/consts/const-eval/strlen.rs b/src/test/ui/consts/const-eval/strlen.rs index 6a5cad82c3aa3..7b14a52354348 100644 --- a/src/test/ui/consts/const-eval/strlen.rs +++ b/src/test/ui/consts/const-eval/strlen.rs @@ -1,9 +1,11 @@ // run-pass -#![feature(const_str_len, const_str_as_bytes)] - const S: &str = "foo"; pub const B: &[u8] = S.as_bytes(); +pub const C: usize = B.len(); +pub const D: bool = B.is_empty(); +pub const E: bool = S.is_empty(); +pub const F: usize = S.len(); pub fn foo() -> [u8; S.len()] { let mut buf = [0; S.len()]; @@ -20,4 +22,10 @@ fn main() { assert_eq!(LEN, S.len()); assert_eq!(B, foo()); assert_eq!(B, b"foo"); + assert_eq!(C, 3); + assert_eq!(F, 3); + assert!(!D); + assert!(!E); + const EMPTY: bool = "".is_empty(); + assert!(EMPTY); } diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs index 4281874a0314d..0b1ab1c34ff2f 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs @@ -12,5 +12,5 @@ fn main() {} const unsafe fn no_union() { union Foo { x: (), y: () } Foo { x: () }.y - //~^ unions in const fn + //~^ accessing union fields is unstable } diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr index 9de0e732f33d2..2a4c627438d61 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr @@ -25,14 +25,14 @@ LL | const unsafe fn bad_const_unsafe_deref_raw_ref(x: *mut usize) -> &'static u = note: for more information, see https://github.com/rust-lang/rust/issues/51911 = help: add `#![feature(const_raw_ptr_deref)]` to the crate attributes to enable -error[E0658]: unions in const fn are unstable +error[E0723]: accessing union fields is unstable --> $DIR/min_const_fn_unsafe_bad.rs:14:5 | LL | Foo { x: () }.y | ^^^^^^^^^^^^^^^ | - = note: for more information, see https://github.com/rust-lang/rust/issues/51909 - = help: add `#![feature(const_fn_union)]` to the crate attributes to enable + = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563 + = help: add `#![feature(const_fn)]` to the crate attributes to enable error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block --> $DIR/min_const_fn_unsafe_bad.rs:1:77 @@ -44,5 +44,5 @@ LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { error: aborting due to 5 previous errors -Some errors have detailed explanations: E0133, E0658. +Some errors have detailed explanations: E0133, E0658, E0723. For more information about an error, try `rustc --explain E0133`. diff --git a/src/test/ui/issues/issue-52060.rs b/src/test/ui/issues/issue-52060.rs index 54eff228934e3..13b914c0331d1 100644 --- a/src/test/ui/issues/issue-52060.rs +++ b/src/test/ui/issues/issue-52060.rs @@ -3,6 +3,5 @@ static A: &'static [u32] = &[1]; static B: [u32; 1] = [0; A.len()]; //~^ ERROR [E0013] -//~| ERROR `core::slice::::len` is not yet stable as a const fn fn main() {} diff --git a/src/test/ui/issues/issue-52060.stderr b/src/test/ui/issues/issue-52060.stderr index 7c3f7695549f0..2f90f7f9e035b 100644 --- a/src/test/ui/issues/issue-52060.stderr +++ b/src/test/ui/issues/issue-52060.stderr @@ -4,14 +4,6 @@ error[E0013]: constants cannot refer to statics, use a constant instead LL | static B: [u32; 1] = [0; A.len()]; | ^ -error: `core::slice::::len` is not yet stable as a const fn - --> $DIR/issue-52060.rs:4:26 - | -LL | static B: [u32; 1] = [0; A.len()]; - | ^^^^^^^ - | - = help: add `#![feature(const_slice_len)]` to the crate attributes to enable - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0013`. From 62dc7948d1e6b45e25a2ce177f76f257f3a5c1a4 Mon Sep 17 00:00:00 2001 From: jordins Date: Tue, 24 Sep 2019 15:25:24 +0200 Subject: [PATCH 139/413] fix several issues in String docs - In some places &str was shown instead of String. - into_bytes is the reverse of from_utf8 Fixes #63797 --- src/liballoc/string.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 1166e7b5df295..e5f96ada6d5ee 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -429,7 +429,7 @@ impl String { /// Converts a vector of bytes to a `String`. /// - /// A string slice ([`&str`]) is made of bytes ([`u8`]), and a vector of bytes + /// A string ([`String`]) is made of bytes ([`u8`]), and a vector of bytes /// ([`Vec`]) is made of bytes, so this function converts between the /// two. Not all byte slices are valid `String`s, however: `String` /// requires that it is valid UTF-8. `from_utf8()` checks to ensure that @@ -446,7 +446,7 @@ impl String { /// If you need a [`&str`] instead of a `String`, consider /// [`str::from_utf8`]. /// - /// The inverse of this method is [`as_bytes`]. + /// The inverse of this method is [`into_bytes`]. /// /// # Errors /// @@ -480,11 +480,11 @@ impl String { /// with this error. /// /// [`from_utf8_unchecked`]: struct.String.html#method.from_utf8_unchecked - /// [`&str`]: ../../std/primitive.str.html + /// [`String`]: struct.String.html /// [`u8`]: ../../std/primitive.u8.html /// [`Vec`]: ../../std/vec/struct.Vec.html /// [`str::from_utf8`]: ../../std/str/fn.from_utf8.html - /// [`as_bytes`]: struct.String.html#method.as_bytes + /// [`into_bytes`]: struct.String.html#method.into_bytes /// [`FromUtf8Error`]: struct.FromUtf8Error.html /// [`Err`]: ../../std/result/enum.Result.html#variant.Err #[inline] From 03ac54aed6f728ab4e5e18a10b5c3887782924cf Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 24 Sep 2019 16:14:43 +0200 Subject: [PATCH 140/413] Add const-eval support for SIMD types, insert, and extract --- src/librustc_mir/interpret/intrinsics.rs | 20 +++++++- src/librustc_mir/interpret/operand.rs | 15 ++++++ src/librustc_mir/interpret/place.rs | 34 +++++++++++++ src/librustc_mir/interpret/terminator.rs | 4 +- .../ui/consts/const-eval/const_eval-simd.rs | 24 ++++++++++ .../consts/const-eval/const_eval-simd.stderr | 48 +++++++++++++++++++ 6 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/consts/const-eval/const_eval-simd.rs create mode 100644 src/test/ui/consts/const-eval/const_eval-simd.stderr diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index ec09e69ec8537..0ede068190597 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -239,7 +239,25 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { "transmute" => { self.copy_op_transmute(args[0], dest)?; } - + "simd_insert" => { + let mut vector = self.read_vector(args[0])?; + let index = self.read_scalar(args[1])?.to_u32()? as usize; + let scalar = self.read_immediate(args[2])?; + if vector[index].layout.size == scalar.layout.size { + vector[index] = scalar; + } else { + throw_ub_format!( + "Inserting `{:?}` with size `{}` to a vector element place of size `{}`", + scalar, scalar.layout.size.bytes(), vector[index].layout.size.bytes() + ); + } + self.write_vector(vector, dest)?; + } + "simd_extract" => { + let index = self.read_scalar(args[1])?.to_u32()? as _; + let scalar = self.read_immediate(self.operand_field(args[0], index)?)?; + self.write_immediate(*scalar, dest)?; + } _ => return Ok(false), } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index dd214c4a031f7..184e2ee9516fc 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -335,6 +335,21 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } + /// Read vector from operand `op` + pub fn read_vector(&self, op: OpTy<'tcx, M::PointerTag>) + -> InterpResult<'tcx, Vec>> { + if let layout::Abi::Vector { count, .. } = op.layout.abi { + assert_ne!(count, 0); + let mut scalars = Vec::new(); + for index in 0..count { + scalars.push(self.read_immediate(self.operand_field(op, index as _)?)?); + } + Ok(scalars) + } else { + bug!("type is not a vector: {:?}, abi: {:?}", op.layout.ty, op.layout.abi); + } + } + /// Read a scalar from a place pub fn read_scalar( &self, diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index c3660fb7a2e28..9154e2666c598 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -696,6 +696,40 @@ where Ok(()) } + /// Writes the `scalar` to the `index`-th element of the `vector`. + pub fn write_scalar_to_vector( + &mut self, + scalar: ImmTy<'tcx, M::PointerTag>, + vector: PlaceTy<'tcx, M::PointerTag>, + index: usize, + ) -> InterpResult<'tcx> { + let index = index as u64; + let place = self.place_field(vector, index)?; + self.write_immediate(*scalar, place)?; + Ok(()) + } + + /// Writes the `scalars` to the `vector`. + pub fn write_vector( + &mut self, + scalars: Vec>, + vector: PlaceTy<'tcx, M::PointerTag>, + ) -> InterpResult<'tcx> { + assert_ne!(scalars.len(), 0); + match vector.layout.ty.sty { + ty::Adt(def, ..) if def.repr.simd() => { + let tcx = &*self.tcx; + let count = vector.layout.ty.simd_size(*tcx); + assert_eq!(count, scalars.len()); + for index in 0..scalars.len() { + self.write_scalar_to_vector(scalars[index], vector, index)?; + } + } + _ => bug!("not a vector"), + } + Ok(()) + } + /// Write an `Immediate` to memory. #[inline(always)] pub fn write_immediate_to_mplace( diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 8310ef02f9669..a324c58512406 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -249,7 +249,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { match instance.def { ty::InstanceDef::Intrinsic(..) => { - if caller_abi != Abi::RustIntrinsic { + if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = caller_abi { + // ok + } else { throw_unsup!(FunctionAbiMismatch(caller_abi, Abi::RustIntrinsic)) } // The intrinsic itself cannot diverge, so if we got here without a return diff --git a/src/test/ui/consts/const-eval/const_eval-simd.rs b/src/test/ui/consts/const-eval/const_eval-simd.rs new file mode 100644 index 0000000000000..a0f088cc636fc --- /dev/null +++ b/src/test/ui/consts/const-eval/const_eval-simd.rs @@ -0,0 +1,24 @@ +// run-pass +// compile-flags: -Zunleash-the-miri-inside-of-you +#![feature(repr_simd)] +#![feature(platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] struct i8x1(i8); + +extern "platform-intrinsic" { + fn simd_insert(x: T, idx: u32, val: U) -> T; + fn simd_extract(x: T, idx: u32) -> U; +} + +const fn foo(x: i8x1) -> i8 { + unsafe { simd_insert(x, 0_u32, 42_i8) }.0 +} + +fn main() { + const V: i8x1 = i8x1(13); + const X: i8 = foo(V); + const Y: i8 = unsafe { simd_extract(V, 0) }; + assert_eq!(X, 42); + assert_eq!(Y, 13); +} diff --git a/src/test/ui/consts/const-eval/const_eval-simd.stderr b/src/test/ui/consts/const-eval/const_eval-simd.stderr new file mode 100644 index 0000000000000..7fc068718b0be --- /dev/null +++ b/src/test/ui/consts/const-eval/const_eval-simd.stderr @@ -0,0 +1,48 @@ +warning: skipping const checks + --> $DIR/const_eval-simd.rs:22:5 + | +LL | assert_eq!(X, 42); + | ^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_eval-simd.rs:22:5 + | +LL | assert_eq!(X, 42); + | ^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_eval-simd.rs:22:5 + | +LL | assert_eq!(X, 42); + | ^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_eval-simd.rs:23:5 + | +LL | assert_eq!(Y, 13); + | ^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_eval-simd.rs:23:5 + | +LL | assert_eq!(Y, 13); + | ^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/const_eval-simd.rs:23:5 + | +LL | assert_eq!(Y, 13); + | ^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + From 75d8199ab1f41be3f58b5f5331eb642714f42732 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 24 Sep 2019 16:48:17 +0200 Subject: [PATCH 141/413] Add a fail test --- .../consts/const-eval/const_eval-simd_fail.rs | 20 +++++++++++++++++++ .../const-eval/const_eval-simd_fail.stderr | 16 +++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/test/ui/consts/const-eval/const_eval-simd_fail.rs create mode 100644 src/test/ui/consts/const-eval/const_eval-simd_fail.stderr diff --git a/src/test/ui/consts/const-eval/const_eval-simd_fail.rs b/src/test/ui/consts/const-eval/const_eval-simd_fail.rs new file mode 100644 index 0000000000000..20c839a81a04e --- /dev/null +++ b/src/test/ui/consts/const-eval/const_eval-simd_fail.rs @@ -0,0 +1,20 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +#![feature(repr_simd)] +#![feature(platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] struct i8x1(i8); + +extern "platform-intrinsic" { + fn simd_insert(x: T, idx: u32, val: U) -> T; +} + +const fn foo(x: i8x1) -> i8 { + // 42 is a i16 that does not fit in a i8 + unsafe { simd_insert(x, 0_u32, 42_i16) }.0 //~ ERROR +} + +fn main() { + const V: i8x1 = i8x1(13); + const X: i8 = foo(V); +} diff --git a/src/test/ui/consts/const-eval/const_eval-simd_fail.stderr b/src/test/ui/consts/const-eval/const_eval-simd_fail.stderr new file mode 100644 index 0000000000000..9f76287979a60 --- /dev/null +++ b/src/test/ui/consts/const-eval/const_eval-simd_fail.stderr @@ -0,0 +1,16 @@ +error: any use of this value will cause an error + --> $DIR/const_eval-simd_fail.rs:14:14 + | +LL | unsafe { simd_insert(x, 0_u32, 42_i16) }.0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | Inserting `i16` with size `2` to a vector element place of size `1` + | inside call to `foo` at $DIR/const_eval-simd_fail.rs:19:19 +... +LL | const X: i8 = foo(V); + | --------------------- + | + = note: `#[deny(const_err)]` on by default + +error: aborting due to previous error + From f0bbd2b71c4861efc11599fe763f80b5de4490cd Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 24 Sep 2019 16:52:03 +0200 Subject: [PATCH 142/413] Move tests to SIMD subdirectory --- src/librustc_mir/interpret/intrinsics.rs | 4 ++-- .../insert_extract-fail.rs} | 0 .../insert_extract-fail.stderr} | 4 ++-- .../{const_eval-simd.rs => simd/insert_extract.rs} | 0 .../insert_extract.stderr} | 12 ++++++------ 5 files changed, 10 insertions(+), 10 deletions(-) rename src/test/ui/consts/const-eval/{const_eval-simd_fail.rs => simd/insert_extract-fail.rs} (100%) rename src/test/ui/consts/const-eval/{const_eval-simd_fail.stderr => simd/insert_extract-fail.stderr} (77%) rename src/test/ui/consts/const-eval/{const_eval-simd.rs => simd/insert_extract.rs} (100%) rename src/test/ui/consts/const-eval/{const_eval-simd.stderr => simd/insert_extract.stderr} (87%) diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 0ede068190597..630f5010b8598 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -247,8 +247,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { vector[index] = scalar; } else { throw_ub_format!( - "Inserting `{:?}` with size `{}` to a vector element place of size `{}`", - scalar, scalar.layout.size.bytes(), vector[index].layout.size.bytes() + "Inserting `{}` with size `{}` to a vector element place of size `{}`", + scalar.layout.ty, scalar.layout.size.bytes(), vector[index].layout.size.bytes() ); } self.write_vector(vector, dest)?; diff --git a/src/test/ui/consts/const-eval/const_eval-simd_fail.rs b/src/test/ui/consts/const-eval/simd/insert_extract-fail.rs similarity index 100% rename from src/test/ui/consts/const-eval/const_eval-simd_fail.rs rename to src/test/ui/consts/const-eval/simd/insert_extract-fail.rs diff --git a/src/test/ui/consts/const-eval/const_eval-simd_fail.stderr b/src/test/ui/consts/const-eval/simd/insert_extract-fail.stderr similarity index 77% rename from src/test/ui/consts/const-eval/const_eval-simd_fail.stderr rename to src/test/ui/consts/const-eval/simd/insert_extract-fail.stderr index 9f76287979a60..cf4e6887f16d5 100644 --- a/src/test/ui/consts/const-eval/const_eval-simd_fail.stderr +++ b/src/test/ui/consts/const-eval/simd/insert_extract-fail.stderr @@ -1,11 +1,11 @@ error: any use of this value will cause an error - --> $DIR/const_eval-simd_fail.rs:14:14 + --> $DIR/insert_extract-fail.rs:14:14 | LL | unsafe { simd_insert(x, 0_u32, 42_i16) }.0 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | Inserting `i16` with size `2` to a vector element place of size `1` - | inside call to `foo` at $DIR/const_eval-simd_fail.rs:19:19 + | inside call to `foo` at $DIR/insert_extract-fail.rs:19:19 ... LL | const X: i8 = foo(V); | --------------------- diff --git a/src/test/ui/consts/const-eval/const_eval-simd.rs b/src/test/ui/consts/const-eval/simd/insert_extract.rs similarity index 100% rename from src/test/ui/consts/const-eval/const_eval-simd.rs rename to src/test/ui/consts/const-eval/simd/insert_extract.rs diff --git a/src/test/ui/consts/const-eval/const_eval-simd.stderr b/src/test/ui/consts/const-eval/simd/insert_extract.stderr similarity index 87% rename from src/test/ui/consts/const-eval/const_eval-simd.stderr rename to src/test/ui/consts/const-eval/simd/insert_extract.stderr index 7fc068718b0be..51510273a791b 100644 --- a/src/test/ui/consts/const-eval/const_eval-simd.stderr +++ b/src/test/ui/consts/const-eval/simd/insert_extract.stderr @@ -1,5 +1,5 @@ warning: skipping const checks - --> $DIR/const_eval-simd.rs:22:5 + --> $DIR/insert_extract.rs:22:5 | LL | assert_eq!(X, 42); | ^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | assert_eq!(X, 42); = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) warning: skipping const checks - --> $DIR/const_eval-simd.rs:22:5 + --> $DIR/insert_extract.rs:22:5 | LL | assert_eq!(X, 42); | ^^^^^^^^^^^^^^^^^^ @@ -15,7 +15,7 @@ LL | assert_eq!(X, 42); = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) warning: skipping const checks - --> $DIR/const_eval-simd.rs:22:5 + --> $DIR/insert_extract.rs:22:5 | LL | assert_eq!(X, 42); | ^^^^^^^^^^^^^^^^^^ @@ -23,7 +23,7 @@ LL | assert_eq!(X, 42); = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) warning: skipping const checks - --> $DIR/const_eval-simd.rs:23:5 + --> $DIR/insert_extract.rs:23:5 | LL | assert_eq!(Y, 13); | ^^^^^^^^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | assert_eq!(Y, 13); = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) warning: skipping const checks - --> $DIR/const_eval-simd.rs:23:5 + --> $DIR/insert_extract.rs:23:5 | LL | assert_eq!(Y, 13); | ^^^^^^^^^^^^^^^^^^ @@ -39,7 +39,7 @@ LL | assert_eq!(Y, 13); = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) warning: skipping const checks - --> $DIR/const_eval-simd.rs:23:5 + --> $DIR/insert_extract.rs:23:5 | LL | assert_eq!(Y, 13); | ^^^^^^^^^^^^^^^^^^ From e6239bb81796715f66ec468b70d8779f8ccac6bd Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 24 Sep 2019 17:02:01 +0200 Subject: [PATCH 143/413] Add some more tests --- .../consts/const-eval/simd/insert_extract.rs | 47 ++- .../const-eval/simd/insert_extract.stderr | 276 ++++++++++++++++-- 2 files changed, 296 insertions(+), 27 deletions(-) diff --git a/src/test/ui/consts/const-eval/simd/insert_extract.rs b/src/test/ui/consts/const-eval/simd/insert_extract.rs index a0f088cc636fc..136965bf68abf 100644 --- a/src/test/ui/consts/const-eval/simd/insert_extract.rs +++ b/src/test/ui/consts/const-eval/simd/insert_extract.rs @@ -5,20 +5,49 @@ #![allow(non_camel_case_types)] #[repr(simd)] struct i8x1(i8); +#[repr(simd)] struct u16x2(u16, u16); +#[repr(simd)] struct f32x3(f32, f32, f32); extern "platform-intrinsic" { fn simd_insert(x: T, idx: u32, val: U) -> T; fn simd_extract(x: T, idx: u32) -> U; } -const fn foo(x: i8x1) -> i8 { - unsafe { simd_insert(x, 0_u32, 42_i8) }.0 -} - fn main() { - const V: i8x1 = i8x1(13); - const X: i8 = foo(V); - const Y: i8 = unsafe { simd_extract(V, 0) }; - assert_eq!(X, 42); - assert_eq!(Y, 13); + { + const U: i8x1 = i8x1(13); + const V: i8x1 = unsafe { simd_insert(U, 0_u32, 42_i8) }; + const X0: i8 = V.0; + const Y0: i8 = unsafe { simd_extract(V, 0) }; + assert_eq!(X0, 42); + assert_eq!(Y0, 42); + } + { + const U: u16x2 = u16x2(13, 14); + const V: u16x2 = unsafe { simd_insert(U, 1_u32, 42_u16) }; + const X0: u16 = V.0; + const X1: u16 = V.1; + const Y0: u16 = unsafe { simd_extract(V, 0) }; + const Y1: u16 = unsafe { simd_extract(V, 1) }; + assert_eq!(X0, 13); + assert_eq!(X1, 42); + assert_eq!(Y0, 13); + assert_eq!(Y1, 42); + } + { + const U: f32x3 = f32x3(13., 14., 15.); + const V: f32x3 = unsafe { simd_insert(U, 1_u32, 42_f32) }; + const X0: f32 = V.0; + const X1: f32 = V.1; + const X2: f32 = V.2; + const Y0: f32 = unsafe { simd_extract(V, 0) }; + const Y1: f32 = unsafe { simd_extract(V, 1) }; + const Y2: f32 = unsafe { simd_extract(V, 2) }; + assert_eq!(X0, 13.); + assert_eq!(X1, 42.); + assert_eq!(X2, 15.); + assert_eq!(Y0, 13.); + assert_eq!(Y1, 42.); + assert_eq!(Y2, 15.); + } } diff --git a/src/test/ui/consts/const-eval/simd/insert_extract.stderr b/src/test/ui/consts/const-eval/simd/insert_extract.stderr index 51510273a791b..8975241403e74 100644 --- a/src/test/ui/consts/const-eval/simd/insert_extract.stderr +++ b/src/test/ui/consts/const-eval/simd/insert_extract.stderr @@ -1,48 +1,288 @@ warning: skipping const checks - --> $DIR/insert_extract.rs:22:5 + --> $DIR/insert_extract.rs:22:9 | -LL | assert_eq!(X, 42); - | ^^^^^^^^^^^^^^^^^^ +LL | assert_eq!(X0, 42); + | ^^^^^^^^^^^^^^^^^^^ | = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) warning: skipping const checks - --> $DIR/insert_extract.rs:22:5 + --> $DIR/insert_extract.rs:22:9 | -LL | assert_eq!(X, 42); - | ^^^^^^^^^^^^^^^^^^ +LL | assert_eq!(X0, 42); + | ^^^^^^^^^^^^^^^^^^^ | = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) warning: skipping const checks - --> $DIR/insert_extract.rs:22:5 + --> $DIR/insert_extract.rs:22:9 | -LL | assert_eq!(X, 42); - | ^^^^^^^^^^^^^^^^^^ +LL | assert_eq!(X0, 42); + | ^^^^^^^^^^^^^^^^^^^ | = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) warning: skipping const checks - --> $DIR/insert_extract.rs:23:5 + --> $DIR/insert_extract.rs:23:9 | -LL | assert_eq!(Y, 13); - | ^^^^^^^^^^^^^^^^^^ +LL | assert_eq!(Y0, 42); + | ^^^^^^^^^^^^^^^^^^^ | = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) warning: skipping const checks - --> $DIR/insert_extract.rs:23:5 + --> $DIR/insert_extract.rs:23:9 | -LL | assert_eq!(Y, 13); - | ^^^^^^^^^^^^^^^^^^ +LL | assert_eq!(Y0, 42); + | ^^^^^^^^^^^^^^^^^^^ | = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) warning: skipping const checks - --> $DIR/insert_extract.rs:23:5 + --> $DIR/insert_extract.rs:23:9 | -LL | assert_eq!(Y, 13); - | ^^^^^^^^^^^^^^^^^^ +LL | assert_eq!(Y0, 42); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:32:9 + | +LL | assert_eq!(X0, 13); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:32:9 + | +LL | assert_eq!(X0, 13); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:32:9 + | +LL | assert_eq!(X0, 13); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:33:9 + | +LL | assert_eq!(X1, 42); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:33:9 + | +LL | assert_eq!(X1, 42); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:33:9 + | +LL | assert_eq!(X1, 42); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:34:9 + | +LL | assert_eq!(Y0, 13); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:34:9 + | +LL | assert_eq!(Y0, 13); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:34:9 + | +LL | assert_eq!(Y0, 13); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:35:9 + | +LL | assert_eq!(Y1, 42); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:35:9 + | +LL | assert_eq!(Y1, 42); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:35:9 + | +LL | assert_eq!(Y1, 42); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:46:9 + | +LL | assert_eq!(X0, 13.); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:46:9 + | +LL | assert_eq!(X0, 13.); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:46:9 + | +LL | assert_eq!(X0, 13.); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:47:9 + | +LL | assert_eq!(X1, 42.); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:47:9 + | +LL | assert_eq!(X1, 42.); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:47:9 + | +LL | assert_eq!(X1, 42.); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:48:9 + | +LL | assert_eq!(X2, 15.); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:48:9 + | +LL | assert_eq!(X2, 15.); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:48:9 + | +LL | assert_eq!(X2, 15.); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:49:9 + | +LL | assert_eq!(Y0, 13.); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:49:9 + | +LL | assert_eq!(Y0, 13.); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:49:9 + | +LL | assert_eq!(Y0, 13.); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:50:9 + | +LL | assert_eq!(Y1, 42.); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:50:9 + | +LL | assert_eq!(Y1, 42.); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:50:9 + | +LL | assert_eq!(Y1, 42.); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:51:9 + | +LL | assert_eq!(Y2, 15.); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:51:9 + | +LL | assert_eq!(Y2, 15.); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +warning: skipping const checks + --> $DIR/insert_extract.rs:51:9 + | +LL | assert_eq!(Y2, 15.); + | ^^^^^^^^^^^^^^^^^^^^ | = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) From 33e1dd78646e712e7fe159e903fff58bd1734418 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 26 Aug 2019 21:32:14 -0400 Subject: [PATCH 144/413] Fix coherence checking for impl trait in type aliases Fixes #63677 RFC #2071 (impl-trait-existential-types) does not explicitly state how impl trait type alises should interact with coherence. However, there's only one choice which makes sense - coherence should look at the underlying type (i.e. the 'defining' type of the impl trait) of the type alias, just like we do for non-impl-trait type aliases. Specifically, impl trait type alises which resolve to a local type should be treated like a local type with respect to coherence (e.g. impl trait type aliases which resolve to a forieign type should be treated as a foreign type, and those that resolve to a local type should be treated as a local type). Since neither inherent impls nor direct trait impl (i.e. `impl MyType` or `impl MyTrait for MyType`) are allowd for type aliases, this usually does not come up. Before we ever attempt to do coherence checking, we will have errored out if an impl trait type alias was used directly in an 'impl' clause. However, during trait selection, we sometimes need to prove bounds like 'T: Sized' for some type 'T'. If 'T' is an impl trait type alias, this requires to know the coherence behavior for impl trait type aliases when we perform coherence checking. Note: Since determining the underlying type of an impl trait type alias requires us to perform body type checking, this commit causes us to type check some bodies easlier than we otherwise would have. However, since this is done through a query, this shouldn't cause any problems For completeness, I've added an additional test of the coherence-related behavior of impl trait type aliases. --- src/librustc/traits/coherence.rs | 18 +++++++++++----- .../traits/specialize/specialization_graph.rs | 2 +- .../auxiliary/foreign-crate.rs | 2 ++ .../ui/type-alias-impl-trait/coherence.rs | 17 +++++++++++++++ .../ui/type-alias-impl-trait/coherence.stderr | 9 ++++++++ .../issue-63677-type-alias-coherence.rs | 21 +++++++++++++++++++ 6 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/type-alias-impl-trait/auxiliary/foreign-crate.rs create mode 100644 src/test/ui/type-alias-impl-trait/coherence.rs create mode 100644 src/test/ui/type-alias-impl-trait/coherence.stderr create mode 100644 src/test/ui/type-alias-impl-trait/issue-63677-type-alias-coherence.rs diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index b6f0addd77107..ee318b127ae66 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -432,7 +432,7 @@ fn orphan_check_trait_ref<'tcx>( } fn uncovered_tys<'tcx>(tcx: TyCtxt<'_>, ty: Ty<'tcx>, in_crate: InCrate) -> Vec> { - if ty_is_local_constructor(ty, in_crate) { + if ty_is_local_constructor(tcx, ty, in_crate) { vec![] } else if fundamental_ty(ty) { ty.walk_shallow() @@ -451,7 +451,7 @@ fn is_possibly_remote_type(ty: Ty<'_>, _in_crate: InCrate) -> bool { } fn ty_is_local(tcx: TyCtxt<'_>, ty: Ty<'_>, in_crate: InCrate) -> bool { - ty_is_local_constructor(ty, in_crate) || + ty_is_local_constructor(tcx, ty, in_crate) || fundamental_ty(ty) && ty.walk_shallow().any(|t| ty_is_local(tcx, t, in_crate)) } @@ -472,7 +472,7 @@ fn def_id_is_local(def_id: DefId, in_crate: InCrate) -> bool { } } -fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool { +fn ty_is_local_constructor(tcx: TyCtxt<'_>, ty: Ty<'_>, in_crate: InCrate) -> bool { debug!("ty_is_local_constructor({:?})", ty); match ty.sty { @@ -504,6 +504,15 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool { ty::Adt(def, _) => def_id_is_local(def.did, in_crate), ty::Foreign(did) => def_id_is_local(did, in_crate), + ty::Opaque(did, _) => { + // Check the underlying type that this opaque + // type resolves to. + // This recursion will eventually terminate, + // since we've already managed to successfully + // resolve all opaque types by this point + let real_ty = tcx.type_of(did); + ty_is_local_constructor(tcx, real_ty, in_crate) + } ty::Dynamic(ref tt, ..) => { if let Some(principal) = tt.principal() { @@ -518,8 +527,7 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool { ty::UnnormalizedProjection(..) | ty::Closure(..) | ty::Generator(..) | - ty::GeneratorWitness(..) | - ty::Opaque(..) => { + ty::GeneratorWitness(..) => { bug!("ty_is_local invoked on unexpected type: {:?}", ty) } } diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index b43881defdb85..c9a40db41dfde 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -395,7 +395,7 @@ impl<'tcx> Graph { /// The parent of a given impl, which is the `DefId` of the trait when the /// impl is a "specialization root". pub fn parent(&self, child: DefId) -> DefId { - *self.parent.get(&child).unwrap() + *self.parent.get(&child).unwrap_or_else(|| panic!("Failed to get parent for {:?}", child)) } } diff --git a/src/test/ui/type-alias-impl-trait/auxiliary/foreign-crate.rs b/src/test/ui/type-alias-impl-trait/auxiliary/foreign-crate.rs new file mode 100644 index 0000000000000..52802dd8fbb47 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/auxiliary/foreign-crate.rs @@ -0,0 +1,2 @@ +pub trait ForeignTrait {} +pub struct ForeignType(pub T); diff --git a/src/test/ui/type-alias-impl-trait/coherence.rs b/src/test/ui/type-alias-impl-trait/coherence.rs new file mode 100644 index 0000000000000..1c0f83d6c12da --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/coherence.rs @@ -0,0 +1,17 @@ +// aux-build:foreign-crate.rs +#![feature(type_alias_impl_trait)] + +extern crate foreign_crate; + +trait LocalTrait {} +impl LocalTrait for foreign_crate::ForeignType {} + +type AliasOfForeignType = impl LocalTrait; +fn use_alias(val: T) -> AliasOfForeignType { + foreign_crate::ForeignType(val) +} + +impl foreign_crate::ForeignTrait for AliasOfForeignType {} +//~^ ERROR the type parameter `T` is not constrained by the impl trait, self type, or predicates + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/coherence.stderr b/src/test/ui/type-alias-impl-trait/coherence.stderr new file mode 100644 index 0000000000000..6ede0fa14ba70 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/coherence.stderr @@ -0,0 +1,9 @@ +error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates + --> $DIR/coherence.rs:14:6 + | +LL | impl foreign_crate::ForeignTrait for AliasOfForeignType {} + | ^ unconstrained type parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/src/test/ui/type-alias-impl-trait/issue-63677-type-alias-coherence.rs b/src/test/ui/type-alias-impl-trait/issue-63677-type-alias-coherence.rs new file mode 100644 index 0000000000000..28f4a85c9f290 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-63677-type-alias-coherence.rs @@ -0,0 +1,21 @@ +// check-pass +// Regression test for issue #63677 - ensure that +// coherence checking can properly handle 'impl trait' +// in type aliases +#![feature(type_alias_impl_trait)] + +pub trait Trait {} +pub struct S1(T); +pub struct S2(T); + +pub type T1 = impl Trait; +pub type T2 = S1; +pub type T3 = S2; + +impl Trait for S1 {} +impl S2 {} +impl T3 {} + +pub fn use_t1() -> T1 { S1(()) } + +fn main() {} From e8cf46e909bcfb6c77b3efb2a60ed674770e1603 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Tue, 24 Sep 2019 18:36:01 +0200 Subject: [PATCH 145/413] relnotes: make compatibility section more sterile and fix rustc version --- RELEASES.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index ecf49278f4b52..766cf64410c77 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -70,10 +70,10 @@ Misc Compatibility Notes ------------------- -- Unfortunately the [`x86_64-unknown-uefi` platform can not be built][62785] - with rustc 1.39.0. -- The [`armv7-unknown-linux-gnueabihf` platform is also known to have - issues][62896] for certain crates such as libc. +- The [`x86_64-unknown-uefi` platform can not be built][62785] with rustc + 1.38.0. +- The [`armv7-unknown-linux-gnueabihf` platform is known to have + issues][62896] with certain crates such as libc. [60260]: https://github.com/rust-lang/rust/pull/60260/ [61457]: https://github.com/rust-lang/rust/pull/61457/ From 5c5e3facabbeb84ef0e5de0ccbfcfa973927f8d1 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 24 Sep 2019 11:06:56 -0700 Subject: [PATCH 146/413] Update cargo 11 commits in b6c6f685b38d523580813b0031677c2298f458ea..aa6b7e01abce30091cc594cb23a15c46cead6e24 2019-09-19 21:10:09 +0000 to 2019-09-24 17:19:12 +0000 - Fix interpretation of `--features a b` on the CLI (rust-lang/cargo#7419) - Update env_logger requirement from 0.6.0 to 0.7.0 (rust-lang/cargo#7422) - Update some unstable docs (rust-lang/cargo#7407) - Fix xcompile tests. (rust-lang/cargo#7408) - -Ztimings: Fix more scale problems. (rust-lang/cargo#7403) - Fix some rendering issues with -Ztimings. (rust-lang/cargo#7397) - -Ztimings: show max jobs/cpus (rust-lang/cargo#7398) - Fix -Ztimings with doc tests. (rust-lang/cargo#7395) - Add documentation for the -Zdoctest-xcompile feature (rust-lang/cargo#7391) - Fix integration tests waiting for binaries to finish. (rust-lang/cargo#7394) - Extract Platform to a separate crate. (rust-lang/cargo#7375) --- Cargo.lock | 47 ++++++++++++++++++++++++++++++++++------------- src/tools/cargo | 2 +- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5bc1938fee260..2f998c5d012d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -269,6 +269,7 @@ version = "0.40.0" dependencies = [ "atty", "bytesize", + "cargo-platform", "cargo-test-macro", "cargo-test-support", "clap", @@ -278,7 +279,7 @@ dependencies = [ "crypto-hash", "curl", "curl-sys", - "env_logger", + "env_logger 0.7.0", "failure", "filetime", "flate2", @@ -325,6 +326,13 @@ dependencies = [ "winapi 0.3.6", ] +[[package]] +name = "cargo-platform" +version = "0.1.0" +dependencies = [ + "serde", +] + [[package]] name = "cargo-test-macro" version = "0.1.0" @@ -526,7 +534,7 @@ name = "compiletest" version = "0.0.0" dependencies = [ "diff", - "env_logger", + "env_logger 0.6.2", "getopts", "lazy_static 1.3.0", "libc", @@ -938,6 +946,19 @@ dependencies = [ "termcolor", ] +[[package]] +name = "env_logger" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ecdb7dd54465526f0a56d666e3b2dd5f3a218665a030b6e4ad9e70fa95d8fa" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + [[package]] name = "error-chain" version = "0.12.0" @@ -1339,9 +1360,9 @@ checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" [[package]] name = "humantime" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" dependencies = [ "quick-error", ] @@ -1866,7 +1887,7 @@ dependencies = [ "chrono", "clap", "elasticlunr-rs", - "env_logger", + "env_logger 0.6.2", "error-chain", "handlebars", "itertools 0.8.0", @@ -1891,7 +1912,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77d1f0ba4d1e6b86fa18e8853d026d7d76a97eb7eb5eb052ed80901e43b7fc10" dependencies = [ - "env_logger", + "env_logger 0.6.2", "failure", "log", "mdbook", @@ -2084,7 +2105,7 @@ dependencies = [ "colored", "compiletest_rs", "directories", - "env_logger", + "env_logger 0.6.2", "getrandom", "hex 0.3.2", "log", @@ -2493,7 +2514,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df8b3f4e0475def7d9c2e5de8e5a1306949849761e107b360d03e98eafaffd61" dependencies = [ "chrono", - "env_logger", + "env_logger 0.6.2", "log", ] @@ -2620,7 +2641,7 @@ dependencies = [ "bitflags", "clap", "derive_more", - "env_logger", + "env_logger 0.6.2", "humantime", "lazy_static 1.3.0", "log", @@ -2914,7 +2935,7 @@ dependencies = [ "clippy_lints", "crossbeam-channel", "difference", - "env_logger", + "env_logger 0.6.2", "failure", "futures", "heck", @@ -2998,7 +3019,7 @@ name = "rls-rustc" version = "0.6.0" dependencies = [ "clippy_lints", - "env_logger", + "env_logger 0.6.2", "failure", "futures", "log", @@ -3403,7 +3424,7 @@ dependencies = [ name = "rustc_driver" version = "0.0.0" dependencies = [ - "env_logger", + "env_logger 0.6.2", "graphviz", "lazy_static 1.3.0", "log", @@ -3791,7 +3812,7 @@ dependencies = [ "derive-new", "diff", "dirs", - "env_logger", + "env_logger 0.6.2", "failure", "getopts", "ignore", diff --git a/src/tools/cargo b/src/tools/cargo index b6c6f685b38d5..aa6b7e01abce3 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit b6c6f685b38d523580813b0031677c2298f458ea +Subproject commit aa6b7e01abce30091cc594cb23a15c46cead6e24 From 5d79e8c4c97388dd1201135b8d6cfadccfd3c8e3 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 13 Jul 2019 18:02:00 +0300 Subject: [PATCH 147/413] reserve `impl From for T` this is necessary for never-type stabilization --- src/libcore/convert.rs | 6 +++++ src/librustc/traits/select.rs | 21 ++++++++++++--- src/librustc/ty/mod.rs | 28 +++++++++++++------- src/librustc_typeck/check/wfcheck.rs | 29 ++++++++++++--------- src/libsyntax/feature_gate/builtin_attrs.rs | 4 +++ src/libsyntax_pos/symbol.rs | 1 + src/test/ui/never-impl-is-reserved.rs | 12 +++++++++ src/test/ui/never-impl-is-reserved.stderr | 12 +++++++++ 8 files changed, 87 insertions(+), 26 deletions(-) create mode 100644 src/test/ui/never-impl-is-reserved.rs create mode 100644 src/test/ui/never-impl-is-reserved.stderr diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 06f2b7bab12eb..82c20efa9f0d6 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -554,6 +554,12 @@ impl From for T { fn from(t: T) -> T { t } } +#[stable(feature = "convert_infallible", since = "1.34.0")] +#[cfg(not(boostrap_stdarch_ignore_this))] +#[rustc_reservation_impl] +impl From for T { + fn from(t: !) -> T { t } +} // TryFrom implies TryInto #[stable(feature = "try_from", since = "1.34.0")] diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index a54bc05f16961..debd946d7164f 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -50,6 +50,8 @@ use std::iter; use std::rc::Rc; use crate::util::nodemap::{FxHashMap, FxHashSet}; +use syntax::symbol::sym; + pub struct SelectionContext<'cx, 'tcx> { infcx: &'cx InferCtxt<'cx, 'tcx>, @@ -1326,8 +1328,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { (result, dep_node) } - // Treat negative impls as unimplemented - fn filter_negative_impls( + // Treat negative impls as unimplemented, and reservation impls as Ok(None) + fn filter_negative_and_reservation_impls( &self, candidate: SelectionCandidate<'tcx>, ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { @@ -1337,6 +1339,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { { return Err(Unimplemented); } + + if self.tcx().has_attr(def_id, sym::rustc_reservation_impl) { + return Ok(None); + } } Ok(Some(candidate)) } @@ -1453,7 +1459,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Instead, we select the right impl now but report `Bar does // not implement Clone`. if candidates.len() == 1 { - return self.filter_negative_impls(candidates.pop().unwrap()); + return self.filter_negative_and_reservation_impls(candidates.pop().unwrap()); } // Winnow, but record the exact outcome of evaluation, which @@ -1528,7 +1534,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } // Just one candidate left. - self.filter_negative_impls(candidates.pop().unwrap().candidate) + self.filter_negative_and_reservation_impls(candidates.pop().unwrap().candidate) } fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Option { @@ -3728,6 +3734,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Err(()); } + if self.intercrate.is_none() && + self.tcx().has_attr(impl_def_id, sym::rustc_reservation_impl) + { + debug!("match_impl: reservation impls only apply in intercrate mode"); + return Err(()); + } + debug!("match_impl: success impl_substs={:?}", impl_substs); Ok(Normalized { value: impl_substs, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8bb9648e031ef..c5cbe0d0dabe7 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2911,7 +2911,13 @@ impl<'tcx> TyCtxt<'tcx> { return Some(ImplOverlapKind::Permitted); } - let is_legit = if self.features().overlapping_marker_traits { + if self.impl_polarity(def_id1) != self.impl_polarity(def_id2) { + debug!("impls_are_allowed_to_overlap({:?}, {:?}) - different polarities, None", + def_id1, def_id2); + return None; + } + + let is_marker_overlap = if self.features().overlapping_marker_traits { let trait1_is_empty = self.impl_trait_ref(def_id1) .map_or(false, |trait_ref| { self.associated_item_def_ids(trait_ref.def_id).is_empty() @@ -2920,22 +2926,24 @@ impl<'tcx> TyCtxt<'tcx> { .map_or(false, |trait_ref| { self.associated_item_def_ids(trait_ref.def_id).is_empty() }); - self.impl_polarity(def_id1) == self.impl_polarity(def_id2) - && trait1_is_empty - && trait2_is_empty + trait1_is_empty && trait2_is_empty } else { let is_marker_impl = |def_id: DefId| -> bool { let trait_ref = self.impl_trait_ref(def_id); trait_ref.map_or(false, |tr| self.trait_def(tr.def_id).is_marker) }; - self.impl_polarity(def_id1) == self.impl_polarity(def_id2) - && is_marker_impl(def_id1) - && is_marker_impl(def_id2) + is_marker_impl(def_id1) && is_marker_impl(def_id2) }; - if is_legit { - debug!("impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted)", - def_id1, def_id2); + // `#[rustc_reservation_impl]` impls don't overlap with anything + let is_reserve_overlap = { + self.has_attr(def_id1, sym::rustc_reservation_impl) || + self.has_attr(def_id2, sym::rustc_reservation_impl) + }; + + if is_marker_overlap || is_reserve_overlap { + debug!("impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) ({:?}/{:?})", + def_id1, def_id2, is_marker_overlap, is_reserve_overlap); Some(ImplOverlapKind::Permitted) } else { if let Some(self_ty1) = self.issue33140_self_ty(def_id1) { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index b0e886a2aa2eb..87c34d62bde0a 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -398,18 +398,23 @@ fn check_impl<'tcx>( match *ast_trait_ref { Some(ref ast_trait_ref) => { - let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap(); - let trait_ref = - fcx.normalize_associated_types_in( - ast_trait_ref.path.span, &trait_ref); - let obligations = - ty::wf::trait_obligations(fcx, - fcx.param_env, - fcx.body_id, - &trait_ref, - ast_trait_ref.path.span); - for obligation in obligations { - fcx.register_predicate(obligation); + // `#[rustc_reservation_impl]` impls are not real impls and + // therefore don't need to be WF (the trait's `Self: Trait` predicate + // won't hold). + if !fcx.tcx.has_attr(item_def_id, sym::rustc_reservation_impl) { + let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap(); + let trait_ref = + fcx.normalize_associated_types_in( + ast_trait_ref.path.span, &trait_ref); + let obligations = + ty::wf::trait_obligations(fcx, + fcx.param_env, + fcx.body_id, + &trait_ref, + ast_trait_ref.path.span); + for obligation in obligations { + fcx.register_predicate(obligation); + } } } None => { diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index b6e13200f32af..d38489a2f0db9 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -498,6 +498,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ overflow checking behavior of several libcore functions that are inlined \ across crates and will never be stable", ), + rustc_attr!(rustc_reservation_impl, Normal, template!(Word), + "the `#[rustc_reservation_impl]` attribute is internally used \ + for reserving for `for From for T` impl" + ), rustc_attr!( rustc_test_marker, Normal, template!(Word), "the `#[rustc_test_marker]` attribute is used internally to track tests", diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 597ae83572cee..32af930ffb884 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -606,6 +606,7 @@ symbols! { rustc_std_internal_symbol, rustc_symbol_name, rustc_synthetic, + rustc_reservation_impl, rustc_test_marker, rustc_then_this_would_need, rustc_variance, diff --git a/src/test/ui/never-impl-is-reserved.rs b/src/test/ui/never-impl-is-reserved.rs new file mode 100644 index 0000000000000..9d16015bdc129 --- /dev/null +++ b/src/test/ui/never-impl-is-reserved.rs @@ -0,0 +1,12 @@ +// check that the `for T: From` impl is reserved + +#![feature(never_type)] + +pub struct MyFoo; +pub trait MyTrait {} + +impl MyTrait for MyFoo {} +// This will conflict with the first impl if we impl `for T: From`. +impl MyTrait for T where T: From {} //~ ERROR conflicting implementation + +fn main() {} diff --git a/src/test/ui/never-impl-is-reserved.stderr b/src/test/ui/never-impl-is-reserved.stderr new file mode 100644 index 0000000000000..09116eb4f7faf --- /dev/null +++ b/src/test/ui/never-impl-is-reserved.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `MyTrait` for type `MyFoo`: + --> $DIR/never-impl-is-reserved.rs:10:1 + | +LL | impl MyTrait for MyFoo {} + | ---------------------- first implementation here +LL | // This will conflict with the first impl if we impl `for T: From`. +LL | impl MyTrait for T where T: From {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyFoo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. From 9a94ecde04306986dac1b7ca88b4b327b67ea499 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 13 Jul 2019 22:52:57 +0300 Subject: [PATCH 148/413] improve and add tests --- ...rved.rs => never-from-impl-is-reserved.rs} | 0 ...err => never-from-impl-is-reserved.stderr} | 2 +- .../reservation-impl-coherence-conflict.rs | 16 +++++++++++ ...reservation-impl-coherence-conflict.stderr | 11 ++++++++ .../reservation-impl-no-use.rs | 14 ++++++++++ .../reservation-impl-no-use.stderr | 15 ++++++++++ .../reservation-impls/reservation-impl-ok.rs | 28 +++++++++++++++++++ 7 files changed, 85 insertions(+), 1 deletion(-) rename src/test/ui/{never-impl-is-reserved.rs => never-from-impl-is-reserved.rs} (100%) rename src/test/ui/{never-impl-is-reserved.stderr => never-from-impl-is-reserved.stderr} (91%) create mode 100644 src/test/ui/traits/reservation-impls/reservation-impl-coherence-conflict.rs create mode 100644 src/test/ui/traits/reservation-impls/reservation-impl-coherence-conflict.stderr create mode 100644 src/test/ui/traits/reservation-impls/reservation-impl-no-use.rs create mode 100644 src/test/ui/traits/reservation-impls/reservation-impl-no-use.stderr create mode 100644 src/test/ui/traits/reservation-impls/reservation-impl-ok.rs diff --git a/src/test/ui/never-impl-is-reserved.rs b/src/test/ui/never-from-impl-is-reserved.rs similarity index 100% rename from src/test/ui/never-impl-is-reserved.rs rename to src/test/ui/never-from-impl-is-reserved.rs diff --git a/src/test/ui/never-impl-is-reserved.stderr b/src/test/ui/never-from-impl-is-reserved.stderr similarity index 91% rename from src/test/ui/never-impl-is-reserved.stderr rename to src/test/ui/never-from-impl-is-reserved.stderr index 09116eb4f7faf..7e9b21a542933 100644 --- a/src/test/ui/never-impl-is-reserved.stderr +++ b/src/test/ui/never-from-impl-is-reserved.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `MyTrait` for type `MyFoo`: - --> $DIR/never-impl-is-reserved.rs:10:1 + --> $DIR/never-from-impl-is-reserved.rs:10:1 | LL | impl MyTrait for MyFoo {} | ---------------------- first implementation here diff --git a/src/test/ui/traits/reservation-impls/reservation-impl-coherence-conflict.rs b/src/test/ui/traits/reservation-impls/reservation-impl-coherence-conflict.rs new file mode 100644 index 0000000000000..1a5266f5583d6 --- /dev/null +++ b/src/test/ui/traits/reservation-impls/reservation-impl-coherence-conflict.rs @@ -0,0 +1,16 @@ +// compile-fail + +// check that reservation impls are accounted for in negative reasoning. + +#![feature(rustc_attrs)] + +trait MyTrait {} +#[rustc_reservation_impl] +impl MyTrait for () {} + +trait OtherTrait {} +impl OtherTrait for () {} +impl OtherTrait for T {} +//~^ ERROR conflicting implementations + +fn main() {} diff --git a/src/test/ui/traits/reservation-impls/reservation-impl-coherence-conflict.stderr b/src/test/ui/traits/reservation-impls/reservation-impl-coherence-conflict.stderr new file mode 100644 index 0000000000000..7b88d2b42db1b --- /dev/null +++ b/src/test/ui/traits/reservation-impls/reservation-impl-coherence-conflict.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `OtherTrait` for type `()`: + --> $DIR/reservation-impl-coherence-conflict.rs:13:1 + | +LL | impl OtherTrait for () {} + | ---------------------- first implementation here +LL | impl OtherTrait for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/traits/reservation-impls/reservation-impl-no-use.rs b/src/test/ui/traits/reservation-impls/reservation-impl-no-use.rs new file mode 100644 index 0000000000000..f08338bdc1c91 --- /dev/null +++ b/src/test/ui/traits/reservation-impls/reservation-impl-no-use.rs @@ -0,0 +1,14 @@ +// compile-fail + +// check that reservation impls can't be used as normal impls in positive reasoning. + +#![feature(rustc_attrs)] + +trait MyTrait { fn foo(&self); } +#[rustc_reservation_impl] +impl MyTrait for () { fn foo(&self) {} } + +fn main() { + <() as MyTrait>::foo(&()); + //~^ ERROR the trait bound `(): MyTrait` is not satisfied +} diff --git a/src/test/ui/traits/reservation-impls/reservation-impl-no-use.stderr b/src/test/ui/traits/reservation-impls/reservation-impl-no-use.stderr new file mode 100644 index 0000000000000..8a86f53086dd5 --- /dev/null +++ b/src/test/ui/traits/reservation-impls/reservation-impl-no-use.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `(): MyTrait` is not satisfied + --> $DIR/reservation-impl-no-use.rs:12:5 + | +LL | trait MyTrait { fn foo(&self); } + | -------------- required by `MyTrait::foo` +... +LL | <() as MyTrait>::foo(&()); + | ^^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `()` + | + = help: the following implementations were found: + <() as MyTrait> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/reservation-impls/reservation-impl-ok.rs b/src/test/ui/traits/reservation-impls/reservation-impl-ok.rs new file mode 100644 index 0000000000000..febd14b792297 --- /dev/null +++ b/src/test/ui/traits/reservation-impls/reservation-impl-ok.rs @@ -0,0 +1,28 @@ +// run-pass + +// rpass test for reservation impls. Not 100% required because `From` uses them, +// but still. + +#![feature(rustc_attrs)] + +use std::mem; + +trait MyTrait { + fn foo(&self, s: S) -> usize; +} + +#[rustc_reservation_impl] +impl MyTrait for T { + fn foo(&self, _x: u64) -> usize { 0 } +} + +// reservation impls don't create coherence conflicts, even with +// non-chain overlap. +impl MyTrait for u32 { + fn foo(&self, _x: S) -> usize { mem::size_of::() } +} + +fn main() { + // ...and the non-reservation impl gets picked.XS + assert_eq!(0u32.foo(0u64), mem::size_of::()); +} From 1ec7ae14fa5b4b29f56d7085f632dd6301ad4815 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sun, 14 Jul 2019 00:09:46 +0300 Subject: [PATCH 149/413] resolve the rustc_reservation_impl attribute in 1 place --- src/librustc/query/mod.rs | 2 +- src/librustc/traits/auto_trait.rs | 2 +- src/librustc/traits/select.rs | 24 ++++++------- src/librustc/ty/mod.rs | 46 ++++++++++++++++-------- src/librustc_metadata/decoder.rs | 2 +- src/librustc_metadata/encoder.rs | 3 +- src/librustc_metadata/schema.rs | 2 +- src/librustc_traits/lowering/mod.rs | 5 +-- src/librustc_typeck/check/wfcheck.rs | 53 +++++++++++++++------------- src/librustc_typeck/collect.rs | 26 ++++++++++++-- src/librustdoc/clean/mod.rs | 13 ++++--- 11 files changed, 112 insertions(+), 66 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index c7260945295a6..b937d1a30409a 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -286,7 +286,7 @@ rustc_queries! { query associated_item(_: DefId) -> ty::AssocItem {} query impl_trait_ref(_: DefId) -> Option> {} - query impl_polarity(_: DefId) -> hir::ImplPolarity {} + query impl_polarity(_: DefId) -> ty::ImplPolarity {} query issue33140_self_ty(_: DefId) -> Option> {} } diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index d89cf8eb3e843..c481943e25e37 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -321,7 +321,7 @@ impl AutoTraitFinder<'tcx> { match vtable { Vtable::VtableImpl(VtableImplData { impl_def_id, .. }) => { // Blame tidy for the weird bracket placement - if infcx.tcx.impl_polarity(*impl_def_id) == hir::ImplPolarity::Negative + if infcx.tcx.impl_polarity(*impl_def_id) == ty::ImplPolarity::Negative { debug!("evaluate_nested_obligations: Found explicit negative impl\ {:?}, bailing out", impl_def_id); diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index debd946d7164f..61bb53dd334fa 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -50,8 +50,6 @@ use std::iter; use std::rc::Rc; use crate::util::nodemap::{FxHashMap, FxHashSet}; -use syntax::symbol::sym; - pub struct SelectionContext<'cx, 'tcx> { infcx: &'cx InferCtxt<'cx, 'tcx>, @@ -1334,15 +1332,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidate: SelectionCandidate<'tcx>, ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { if let ImplCandidate(def_id) = candidate { - if !self.allow_negative_impls - && self.tcx().impl_polarity(def_id) == hir::ImplPolarity::Negative - { - return Err(Unimplemented); - } - - if self.tcx().has_attr(def_id, sym::rustc_reservation_impl) { - return Ok(None); - } + match self.tcx().impl_polarity(def_id) { + ty::ImplPolarity::Negative if !self.allow_negative_impls => { + return Err(Unimplemented); + } + ty::ImplPolarity::Reservation => { + return Ok(None); + } + _ => {} + }; } Ok(Some(candidate)) } @@ -3734,8 +3732,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Err(()); } - if self.intercrate.is_none() && - self.tcx().has_attr(impl_def_id, sym::rustc_reservation_impl) + if self.intercrate.is_none() + && self.tcx().impl_polarity(impl_def_id) == ty::ImplPolarity::Reservation { debug!("match_impl: reservation impls only apply in intercrate mode"); return Err(()); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c5cbe0d0dabe7..b546a24534666 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -167,6 +167,16 @@ pub struct ImplHeader<'tcx> { pub predicates: Vec>, } +#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)] +pub enum ImplPolarity { + /// `impl Trait for Type` + Positive, + /// `impl !Trait for Type` + Negative, + /// `#[rustc_reservation_impl] impl Trait for Type` + Reservation, +} + #[derive(Copy, Clone, Debug, PartialEq, HashStable)] pub struct AssocItem { pub def_id: DefId, @@ -2911,11 +2921,24 @@ impl<'tcx> TyCtxt<'tcx> { return Some(ImplOverlapKind::Permitted); } - if self.impl_polarity(def_id1) != self.impl_polarity(def_id2) { - debug!("impls_are_allowed_to_overlap({:?}, {:?}) - different polarities, None", - def_id1, def_id2); - return None; - } + match (self.impl_polarity(def_id1), self.impl_polarity(def_id2)) { + (ImplPolarity::Reservation, _) | + (_, ImplPolarity::Reservation) => { + // `#[rustc_reservation_impl]` impls don't overlap with anything + debug!("impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (reservations)", + def_id1, def_id2); + return Some(ImplOverlapKind::Permitted); + } + (ImplPolarity::Positive, ImplPolarity::Negative) | + (ImplPolarity::Negative, ImplPolarity::Positive) => { + // FIXME: when can this happen? + debug!("impls_are_allowed_to_overlap({:?}, {:?}) - None (differing polarities)", + def_id1, def_id2); + return None; + } + (ImplPolarity::Positive, ImplPolarity::Positive) | + (ImplPolarity::Negative, ImplPolarity::Negative) => {} + }; let is_marker_overlap = if self.features().overlapping_marker_traits { let trait1_is_empty = self.impl_trait_ref(def_id1) @@ -2935,15 +2958,10 @@ impl<'tcx> TyCtxt<'tcx> { is_marker_impl(def_id1) && is_marker_impl(def_id2) }; - // `#[rustc_reservation_impl]` impls don't overlap with anything - let is_reserve_overlap = { - self.has_attr(def_id1, sym::rustc_reservation_impl) || - self.has_attr(def_id2, sym::rustc_reservation_impl) - }; - if is_marker_overlap || is_reserve_overlap { - debug!("impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) ({:?}/{:?})", - def_id1, def_id2, is_marker_overlap, is_reserve_overlap); + if is_marker_overlap { + debug!("impls_are_allowed_to_overlap({:?}, {:?}) = Some(Permitted) (marker overlap)", + def_id1, def_id2); Some(ImplOverlapKind::Permitted) } else { if let Some(self_ty1) = self.issue33140_self_ty(def_id1) { @@ -3325,7 +3343,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { debug!("issue33140_self_ty({:?}), trait-ref={:?}", def_id, trait_ref); let is_marker_like = - tcx.impl_polarity(def_id) == hir::ImplPolarity::Positive && + tcx.impl_polarity(def_id) == ty::ImplPolarity::Positive && tcx.associated_item_def_ids(trait_ref.def_id).is_empty(); // Check whether these impls would be ok for a marker trait. diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 34c84b1d79d4b..9785b69eaf09e 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -722,7 +722,7 @@ impl<'a, 'tcx> CrateMetadata { self.get_impl_data(id).parent_impl } - pub fn get_impl_polarity(&self, id: DefIndex) -> hir::ImplPolarity { + pub fn get_impl_polarity(&self, id: DefIndex) -> ty::ImplPolarity { self.get_impl_data(id).polarity } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index f430f01542efe..9bf0eefd9fe70 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1172,8 +1172,9 @@ impl EncodeContext<'tcx> { ctor_sig: None, }), repr_options) } - hir::ItemKind::Impl(_, polarity, defaultness, ..) => { + hir::ItemKind::Impl(_, _, defaultness, ..) => { let trait_ref = tcx.impl_trait_ref(def_id); + let polarity = tcx.impl_polarity(def_id); let parent = if let Some(trait_ref) = trait_ref { let trait_def = tcx.trait_def(trait_ref.def_id); trait_def.ancestors(tcx, def_id).nth(1).and_then(|node| { diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 1a5f0e17ba7ce..90967c7933323 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -327,7 +327,7 @@ pub struct TraitAliasData<'tcx> { #[derive(RustcEncodable, RustcDecodable)] pub struct ImplData<'tcx> { - pub polarity: hir::ImplPolarity, + pub polarity: ty::ImplPolarity, pub defaultness: hir::Defaultness, pub parent_impl: Option, diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs index 1558ce1bced52..51d49f0d59ae7 100644 --- a/src/librustc_traits/lowering/mod.rs +++ b/src/librustc_traits/lowering/mod.rs @@ -4,7 +4,7 @@ use rustc::hir::def::DefKind; use rustc::hir::def_id::DefId; use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc::hir::map::definitions::DefPathData; -use rustc::hir::{self, ImplPolarity}; +use rustc::hir; use rustc::traits::{ Clause, Clauses, @@ -295,7 +295,8 @@ fn program_clauses_for_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> { } fn program_clauses_for_impl(tcx: TyCtxt<'tcx>, def_id: DefId) -> Clauses<'tcx> { - if let ImplPolarity::Negative = tcx.impl_polarity(def_id) { + // FIXME: implement reservation impls. + if let ty::ImplPolarity::Negative = tcx.impl_polarity(def_id) { return List::empty(); } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 87c34d62bde0a..e0e878ffdcc47 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -94,20 +94,27 @@ pub fn check_item_well_formed(tcx: TyCtxt<'_>, def_id: DefId) { // // won't be allowed unless there's an *explicit* implementation of `Send` // for `T` - hir::ItemKind::Impl(_, polarity, defaultness, _, ref trait_ref, ref self_ty, _) => { + hir::ItemKind::Impl(_, _, defaultness, _, ref trait_ref, ref self_ty, _) => { let is_auto = tcx.impl_trait_ref(tcx.hir().local_def_id(item.hir_id)) - .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id)); + .map_or(false, |trait_ref| tcx.trait_is_auto(trait_ref.def_id)); + let polarity = tcx.impl_polarity(def_id); if let (hir::Defaultness::Default { .. }, true) = (defaultness, is_auto) { tcx.sess.span_err(item.span, "impls of auto traits cannot be default"); } - if polarity == hir::ImplPolarity::Positive { - check_impl(tcx, item, self_ty, trait_ref); - } else { - // FIXME(#27579): what amount of WF checking do we need for neg impls? - if trait_ref.is_some() && !is_auto { - span_err!(tcx.sess, item.span, E0192, - "negative impls are only allowed for \ - auto traits (e.g., `Send` and `Sync`)") + match polarity { + ty::ImplPolarity::Positive => { + check_impl(tcx, item, self_ty, trait_ref); + } + ty::ImplPolarity::Negative => { + // FIXME(#27579): what amount of WF checking do we need for neg impls? + if trait_ref.is_some() && !is_auto { + span_err!(tcx.sess, item.span, E0192, + "negative impls are only allowed for \ + auto traits (e.g., `Send` and `Sync`)") + } + } + ty::ImplPolarity::Reservation => { + // FIXME: what amount of WF checking do we need for reservation impls? } } } @@ -401,20 +408,18 @@ fn check_impl<'tcx>( // `#[rustc_reservation_impl]` impls are not real impls and // therefore don't need to be WF (the trait's `Self: Trait` predicate // won't hold). - if !fcx.tcx.has_attr(item_def_id, sym::rustc_reservation_impl) { - let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap(); - let trait_ref = - fcx.normalize_associated_types_in( - ast_trait_ref.path.span, &trait_ref); - let obligations = - ty::wf::trait_obligations(fcx, - fcx.param_env, - fcx.body_id, - &trait_ref, - ast_trait_ref.path.span); - for obligation in obligations { - fcx.register_predicate(obligation); - } + let trait_ref = fcx.tcx.impl_trait_ref(item_def_id).unwrap(); + let trait_ref = + fcx.normalize_associated_types_in( + ast_trait_ref.path.span, &trait_ref); + let obligations = + ty::wf::trait_obligations(fcx, + fcx.param_env, + fcx.body_id, + &trait_ref, + ast_trait_ref.path.span); + for obligation in obligations { + fcx.register_predicate(obligation); } } None => { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index d2e9203779cc8..4503bb264a5f7 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1866,10 +1866,30 @@ fn impl_trait_ref(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { } } -fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> hir::ImplPolarity { +fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity { let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); - match tcx.hir().expect_item(hir_id).node { - hir::ItemKind::Impl(_, polarity, ..) => polarity, + let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); + let item = tcx.hir().expect_item(hir_id); + match &item.node { + hir::ItemKind::Impl(_, hir::ImplPolarity::Negative, ..) => { + if is_rustc_reservation { + tcx.sess.span_err(item.span, "reservation impls can't be negative"); + } + ty::ImplPolarity::Negative + } + hir::ItemKind::Impl(_, hir::ImplPolarity::Positive, _, _, None, _, _) => { + if is_rustc_reservation { + tcx.sess.span_err(item.span, "reservation impls can't be inherent"); + } + ty::ImplPolarity::Positive + } + hir::ItemKind::Impl(_, hir::ImplPolarity::Positive, _, _, Some(_tr), _, _) => { + if is_rustc_reservation { + ty::ImplPolarity::Reservation + } else { + ty::ImplPolarity::Positive + } + } ref item => bug!("impl_polarity: {:?} not an impl", item), } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ae70fdc530be6..15ada0952c8a3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3864,11 +3864,13 @@ pub enum ImplPolarity { Negative, } -impl Clean for hir::ImplPolarity { +impl Clean for ty::ImplPolarity { fn clean(&self, _: &DocContext<'_>) -> ImplPolarity { match self { - &hir::ImplPolarity::Positive => ImplPolarity::Positive, - &hir::ImplPolarity::Negative => ImplPolarity::Negative, + &ty::ImplPolarity::Positive | + // FIXME: do we want to do something else here? + &ty::ImplPolarity::Reservation => ImplPolarity::Positive, + &ty::ImplPolarity::Negative => ImplPolarity::Negative, } } } @@ -3900,6 +3902,7 @@ impl Clean> for doctree::Impl<'_> { let mut ret = Vec::new(); let trait_ = self.trait_.clean(cx); let items = self.items.iter().map(|ii| ii.clean(cx)).collect::>(); + let def_id = cx.tcx.hir().local_def_id(self.id); // If this impl block is an implementation of the Deref trait, then we // need to try inlining the target's inherent impl blocks as well. @@ -3918,7 +3921,7 @@ impl Clean> for doctree::Impl<'_> { name: None, attrs: self.attrs.clean(cx), source: self.whence.clean(cx), - def_id: cx.tcx.hir().local_def_id(self.id), + def_id, visibility: self.vis.clean(cx), stability: cx.stability(self.id).clean(cx), deprecation: cx.deprecation(self.id).clean(cx), @@ -3929,7 +3932,7 @@ impl Clean> for doctree::Impl<'_> { trait_, for_: self.for_.clean(cx), items, - polarity: Some(self.polarity.clean(cx)), + polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)), synthetic: false, blanket_impl: None, }) From b5665e811ba4eca0f778efb65bd3e4a69f4c3ca6 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 27 Jul 2019 20:44:14 +0300 Subject: [PATCH 150/413] improve comments --- src/librustc/traits/select.rs | 2 +- src/librustc/ty/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 61bb53dd334fa..de1c71a1ba31f 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1326,7 +1326,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { (result, dep_node) } - // Treat negative impls as unimplemented, and reservation impls as Ok(None) + // Treat negative impls as unimplemented, and reservation impls as ambiguity. fn filter_negative_and_reservation_impls( &self, candidate: SelectionCandidate<'tcx>, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index b546a24534666..6a9d7eb0750ba 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2931,7 +2931,7 @@ impl<'tcx> TyCtxt<'tcx> { } (ImplPolarity::Positive, ImplPolarity::Negative) | (ImplPolarity::Negative, ImplPolarity::Positive) => { - // FIXME: when can this happen? + // `impl AutoTrait for Type` + `impl !AutoTrait for Type` debug!("impls_are_allowed_to_overlap({:?}, {:?}) - None (differing polarities)", def_id1, def_id2); return None; From 9196b2d0c89b8af853f8f41b5854655932491758 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 27 Jul 2019 22:18:34 +0300 Subject: [PATCH 151/413] add error message for case --- src/libcore/convert.rs | 7 ++++- src/librustc/traits/select.rs | 31 +++++++++++++++++-- src/libsyntax/feature_gate/builtin_attrs.rs | 3 +- .../ui/never-from-impl-is-reserved.stderr | 2 ++ .../reservation-impl-coherence-conflict.rs | 2 +- ...reservation-impl-coherence-conflict.stderr | 2 ++ .../reservation-impl-no-use.rs | 2 +- .../reservation-impls/reservation-impl-ok.rs | 2 +- 8 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 82c20efa9f0d6..6edd56f749290 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -556,7 +556,12 @@ impl From for T { #[stable(feature = "convert_infallible", since = "1.34.0")] #[cfg(not(boostrap_stdarch_ignore_this))] -#[rustc_reservation_impl] +#[rustc_reservation_impl="a future version of Rust might implement `From` for \ + all types. \ + However, it is OK to implement `From` for types you own - \ + when the blanket impl will be added, coherence will be changed \ + to make these impls not be an error." +] impl From for T { fn from(t: !) -> T { t } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index de1c71a1ba31f..c91ee1b9caa93 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -43,6 +43,8 @@ use crate::hir; use rustc_data_structures::bit_set::GrowableBitSet; use rustc_data_structures::sync::Lock; use rustc_target::spec::abi::Abi; +use syntax::attr; +use syntax::symbol::sym; use std::cell::{Cell, RefCell}; use std::cmp; use std::fmt::{self, Display}; @@ -99,6 +101,9 @@ pub enum IntercrateAmbiguityCause { trait_desc: String, self_desc: Option, }, + ReservationImpl { + message: String + }, } impl IntercrateAmbiguityCause { @@ -139,6 +144,11 @@ impl IntercrateAmbiguityCause { trait_desc, self_desc ) } + &IntercrateAmbiguityCause::ReservationImpl { + ref message + } => { + message.clone() + } } } } @@ -1328,15 +1338,32 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Treat negative impls as unimplemented, and reservation impls as ambiguity. fn filter_negative_and_reservation_impls( - &self, + &mut self, candidate: SelectionCandidate<'tcx>, ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { if let ImplCandidate(def_id) = candidate { - match self.tcx().impl_polarity(def_id) { + let tcx = self.tcx(); + match tcx.impl_polarity(def_id) { ty::ImplPolarity::Negative if !self.allow_negative_impls => { return Err(Unimplemented); } ty::ImplPolarity::Reservation => { + if let Some(intercrate_ambiguity_clauses) + = &mut self.intercrate_ambiguity_causes + { + let attrs = tcx.get_attrs(def_id); + let attr = attr::find_by_name(&attrs, sym::rustc_reservation_impl); + let value = attr.and_then(|a| a.value_str()); + if let Some(value) = value { + debug!("filter_negative_and_reservation_impls: \ + reservation impl ambiguity on {:?}", def_id); + intercrate_ambiguity_clauses.push( + IntercrateAmbiguityCause::ReservationImpl { + message: value.to_string() + } + ); + } + } return Ok(None); } _ => {} diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index d38489a2f0db9..d14afc6deaa69 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -457,7 +457,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // ========================================================================== // Internal attributes, Misc: // ========================================================================== - gated!( lang, Normal, template!(NameValueStr: "name"), lang_items, "language items are subject to change", @@ -498,7 +497,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ overflow checking behavior of several libcore functions that are inlined \ across crates and will never be stable", ), - rustc_attr!(rustc_reservation_impl, Normal, template!(Word), + rustc_attr!(rustc_reservation_impl, Normal, template!(NameValueStr: "reservation message"), "the `#[rustc_reservation_impl]` attribute is internally used \ for reserving for `for From for T` impl" ), diff --git a/src/test/ui/never-from-impl-is-reserved.stderr b/src/test/ui/never-from-impl-is-reserved.stderr index 7e9b21a542933..352fed7ca4515 100644 --- a/src/test/ui/never-from-impl-is-reserved.stderr +++ b/src/test/ui/never-from-impl-is-reserved.stderr @@ -6,6 +6,8 @@ LL | impl MyTrait for MyFoo {} LL | // This will conflict with the first impl if we impl `for T: From`. LL | impl MyTrait for T where T: From {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyFoo` + | + = note: a future version of Rust might implement `From` for all types. However, it is OK to implement `From` for types you own - when the blanket impl will be added, coherence will be changed to make these impls not be an error. error: aborting due to previous error diff --git a/src/test/ui/traits/reservation-impls/reservation-impl-coherence-conflict.rs b/src/test/ui/traits/reservation-impls/reservation-impl-coherence-conflict.rs index 1a5266f5583d6..775278c30cd4c 100644 --- a/src/test/ui/traits/reservation-impls/reservation-impl-coherence-conflict.rs +++ b/src/test/ui/traits/reservation-impls/reservation-impl-coherence-conflict.rs @@ -5,7 +5,7 @@ #![feature(rustc_attrs)] trait MyTrait {} -#[rustc_reservation_impl] +#[rustc_reservation_impl="this impl is reserved"] impl MyTrait for () {} trait OtherTrait {} diff --git a/src/test/ui/traits/reservation-impls/reservation-impl-coherence-conflict.stderr b/src/test/ui/traits/reservation-impls/reservation-impl-coherence-conflict.stderr index 7b88d2b42db1b..47e141bd048eb 100644 --- a/src/test/ui/traits/reservation-impls/reservation-impl-coherence-conflict.stderr +++ b/src/test/ui/traits/reservation-impls/reservation-impl-coherence-conflict.stderr @@ -5,6 +5,8 @@ LL | impl OtherTrait for () {} | ---------------------- first implementation here LL | impl OtherTrait for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()` + | + = note: this impl is reserved error: aborting due to previous error diff --git a/src/test/ui/traits/reservation-impls/reservation-impl-no-use.rs b/src/test/ui/traits/reservation-impls/reservation-impl-no-use.rs index f08338bdc1c91..3391daaabe975 100644 --- a/src/test/ui/traits/reservation-impls/reservation-impl-no-use.rs +++ b/src/test/ui/traits/reservation-impls/reservation-impl-no-use.rs @@ -5,7 +5,7 @@ #![feature(rustc_attrs)] trait MyTrait { fn foo(&self); } -#[rustc_reservation_impl] +#[rustc_reservation_impl = "foo"] impl MyTrait for () { fn foo(&self) {} } fn main() { diff --git a/src/test/ui/traits/reservation-impls/reservation-impl-ok.rs b/src/test/ui/traits/reservation-impls/reservation-impl-ok.rs index febd14b792297..611c8d8841323 100644 --- a/src/test/ui/traits/reservation-impls/reservation-impl-ok.rs +++ b/src/test/ui/traits/reservation-impls/reservation-impl-ok.rs @@ -11,7 +11,7 @@ trait MyTrait { fn foo(&self, s: S) -> usize; } -#[rustc_reservation_impl] +#[rustc_reservation_impl = "foo"] impl MyTrait for T { fn foo(&self, _x: u64) -> usize { 0 } } From d7eb5620804540ce5f48d49fadcf0930d9d24000 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 14 Sep 2019 15:34:42 +0300 Subject: [PATCH 152/413] add test for lattice specialization --- .../reservation-impl-non-lattice-ok.rs | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/test/ui/traits/reservation-impls/reservation-impl-non-lattice-ok.rs diff --git a/src/test/ui/traits/reservation-impls/reservation-impl-non-lattice-ok.rs b/src/test/ui/traits/reservation-impls/reservation-impl-non-lattice-ok.rs new file mode 100644 index 0000000000000..2517052b5e4d7 --- /dev/null +++ b/src/test/ui/traits/reservation-impls/reservation-impl-non-lattice-ok.rs @@ -0,0 +1,56 @@ +// build-pass + +// Check that a reservation impl does not force other impls to follow +// a lattice discipline. + +// Why did we ever want to do this? +// +// We want to eventually add a `impl From for T` impl. That impl conflicts +// with existing impls - at least the `impl From for T` impl. There are +// 2 ways we thought of for dealing with that conflict: +// +// 1. Using specialization and doing some handling for the overlap. The current +// thought is for something like "lattice specialization", which means providing +// an (higher-priority) impl for the intersection of every 2 conflicting impls +// that determines what happens in the intersection case. That's the first +// thing we thought about - see e.g. +// https://github.com/rust-lang/rust/issues/57012#issuecomment-452150775 +// +// 2. The other way is to notice that `impl From for T` is basically a marker +// trait, as you say since its only method is uninhabited, and allow for "marker +// trait overlap", where the conflict "doesn't matter" as there is nothing that +// can cause a conflict. +// +// Now it turned out lattice specialization doesn't work it, because an +// `impl From for Smaht` would require a `impl From for Smaht`, +// breaking backwards-compatibility in a fairly painful way. So if we want to +// go with a known approach, we should go with a "marker trait overlap"-style +// approach. + +#![feature(rustc_attrs, never_type)] + +trait MyTrait {} + +impl MyTrait for ! {} + +trait MyFrom { + fn my_from(x: T) -> Self; +} + +// Given the "normal" impls for From +#[rustc_reservation_impl="this impl is reserved"] +impl MyFrom for T { + fn my_from(x: !) -> Self { match x {} } +} + +impl MyFrom for T { + fn my_from(x: T) -> Self { x } +} + +// ... we *do* want to allow this common pattern, of `From for MySmaht` +struct MySmaht(T); +impl MyFrom for MySmaht { + fn my_from(x: T) -> Self { MySmaht(x) } +} + +fn main() {} From 5de1fafb1569ad12f039562ca86f14730d970a3b Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Wed, 18 Sep 2019 19:37:26 +0300 Subject: [PATCH 153/413] improve comment --- .../reservation-impls/reservation-impl-non-lattice-ok.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/ui/traits/reservation-impls/reservation-impl-non-lattice-ok.rs b/src/test/ui/traits/reservation-impls/reservation-impl-non-lattice-ok.rs index 2517052b5e4d7..ae1556cb4dc88 100644 --- a/src/test/ui/traits/reservation-impls/reservation-impl-non-lattice-ok.rs +++ b/src/test/ui/traits/reservation-impls/reservation-impl-non-lattice-ok.rs @@ -16,10 +16,10 @@ // thing we thought about - see e.g. // https://github.com/rust-lang/rust/issues/57012#issuecomment-452150775 // -// 2. The other way is to notice that `impl From for T` is basically a marker -// trait, as you say since its only method is uninhabited, and allow for "marker -// trait overlap", where the conflict "doesn't matter" as there is nothing that -// can cause a conflict. +// 2. The other way is to notice that `impl From for T` is basically a +// marker trait since its only method is uninhabited, and allow for "marker +// trait overlap", where the conflict "doesn't matter" because it can't +// actually cause any ambiguity. // // Now it turned out lattice specialization doesn't work it, because an // `impl From for Smaht` would require a `impl From for Smaht`, From 68fd593a22c98246857726f576a14651d9ecb997 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 23 Sep 2019 13:51:59 -0400 Subject: [PATCH 154/413] cite reservation impls tracking issue --- src/librustc/ty/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 6a9d7eb0750ba..5a436b28fbcf3 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -174,6 +174,9 @@ pub enum ImplPolarity { /// `impl !Trait for Type` Negative, /// `#[rustc_reservation_impl] impl Trait for Type` + /// + /// This is a "stability hack", not a real Rust feature. + /// See #64631 for details. Reservation, } From b40a64da4fb1f2012bd925100b4cff2a38a72b30 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 23 Sep 2019 13:52:16 -0400 Subject: [PATCH 155/413] remove outdated fixme --- src/librustc_traits/lowering/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs index 51d49f0d59ae7..4c30227150fb1 100644 --- a/src/librustc_traits/lowering/mod.rs +++ b/src/librustc_traits/lowering/mod.rs @@ -295,7 +295,6 @@ fn program_clauses_for_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> { } fn program_clauses_for_impl(tcx: TyCtxt<'tcx>, def_id: DefId) -> Clauses<'tcx> { - // FIXME: implement reservation impls. if let ty::ImplPolarity::Negative = tcx.impl_polarity(def_id) { return List::empty(); } From da60c53fa7fb74d314d3ad4f33ea55479884313a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 23 Sep 2019 13:52:24 -0400 Subject: [PATCH 156/413] nit: update text to avoid "lattice specialization" term --- .../reservation-impl-non-lattice-ok.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/test/ui/traits/reservation-impls/reservation-impl-non-lattice-ok.rs b/src/test/ui/traits/reservation-impls/reservation-impl-non-lattice-ok.rs index ae1556cb4dc88..f14589ccf846d 100644 --- a/src/test/ui/traits/reservation-impls/reservation-impl-non-lattice-ok.rs +++ b/src/test/ui/traits/reservation-impls/reservation-impl-non-lattice-ok.rs @@ -9,11 +9,12 @@ // with existing impls - at least the `impl From for T` impl. There are // 2 ways we thought of for dealing with that conflict: // -// 1. Using specialization and doing some handling for the overlap. The current -// thought is for something like "lattice specialization", which means providing -// an (higher-priority) impl for the intersection of every 2 conflicting impls -// that determines what happens in the intersection case. That's the first -// thing we thought about - see e.g. +// 1. Using specialization and doing some handling for the +// overlap. The current thought is to require ["intersection +// impls"][ii], specialization", which means providing an +// (higher-priority) impl for the intersection of every 2 conflicting +// impls that determines what happens in the intersection case. That's +// the first thing we thought about - see e.g. // https://github.com/rust-lang/rust/issues/57012#issuecomment-452150775 // // 2. The other way is to notice that `impl From for T` is basically a @@ -26,6 +27,8 @@ // breaking backwards-compatibility in a fairly painful way. So if we want to // go with a known approach, we should go with a "marker trait overlap"-style // approach. +// +// [ii]: http://smallcultfollowing.com/babysteps/blog/2016/09/24/intersection-impls/ #![feature(rustc_attrs, never_type)] From 167ab0439eb9f2d7b199f846fe07061b31185e09 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 23 Sep 2019 14:27:34 -0400 Subject: [PATCH 157/413] nit: update error text to cite tracking issue --- src/libcore/convert.rs | 8 ++------ src/test/ui/never-from-impl-is-reserved.stderr | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 6edd56f749290..71edea561b8bb 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -556,12 +556,8 @@ impl From for T { #[stable(feature = "convert_infallible", since = "1.34.0")] #[cfg(not(boostrap_stdarch_ignore_this))] -#[rustc_reservation_impl="a future version of Rust might implement `From` for \ - all types. \ - However, it is OK to implement `From` for types you own - \ - when the blanket impl will be added, coherence will be changed \ - to make these impls not be an error." -] +#[rustc_reservation_impl="permitting this impl would forbid us from adding \ +`impl From for T` later; see rust-lang/rust#64715 for details"] impl From for T { fn from(t: !) -> T { t } } diff --git a/src/test/ui/never-from-impl-is-reserved.stderr b/src/test/ui/never-from-impl-is-reserved.stderr index 352fed7ca4515..8b8d0f4ea73be 100644 --- a/src/test/ui/never-from-impl-is-reserved.stderr +++ b/src/test/ui/never-from-impl-is-reserved.stderr @@ -7,7 +7,7 @@ LL | // This will conflict with the first impl if we impl `for T: From`. LL | impl MyTrait for T where T: From {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `MyFoo` | - = note: a future version of Rust might implement `From` for all types. However, it is OK to implement `From` for types you own - when the blanket impl will be added, coherence will be changed to make these impls not be an error. + = note: permitting this impl would forbid us from adding `impl From for T` later; see rust-lang/rust#64715 for details error: aborting due to previous error From 99dc545552c40212b9d062512cd391af076b51c9 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 24 Sep 2019 11:10:42 -0400 Subject: [PATCH 158/413] add a rustdoc comment to the reservation impl --- src/libcore/convert.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index 71edea561b8bb..f639309db8791 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -554,6 +554,11 @@ impl From for T { fn from(t: T) -> T { t } } +/// **Stability note:** This impl does not yet exist, but we are +/// "reserving space" to add it in the future. See +/// [rust-lang/rust#64715][#64715] for details. +/// +/// [#64715]: https://github.com/rust-lang/rust/issues/64715 #[stable(feature = "convert_infallible", since = "1.34.0")] #[cfg(not(boostrap_stdarch_ignore_this))] #[rustc_reservation_impl="permitting this impl would forbid us from adding \ From d9ab4ff9a3746c8663278f7338cfb4aabf96a9bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 24 Sep 2019 11:05:49 -0700 Subject: [PATCH 159/413] Remove blanket silencing of "type annotation needed" errors Remove blanket check for existence of other errors before emitting "type annotation needed" errors, and add some eager checks to avoid adding obligations when they refer to types that reference `[type error]` in order to reduce unneded errors. --- src/librustc/hir/lowering.rs | 4 +- src/librustc/infer/opaque_types/mod.rs | 13 ++- src/librustc/traits/error_reporting.rs | 71 ++++++++----- src/librustc/traits/mod.rs | 13 ++- src/librustc/traits/select.rs | 2 +- src/librustc/traits/structural_impls.rs | 3 +- src/librustc/ty/mod.rs | 6 +- src/librustc_typeck/check/coercion.rs | 2 +- src/librustc_typeck/check/expr.rs | 16 +-- src/librustc_typeck/check/mod.rs | 4 +- src/librustc_typeck/check/wfcheck.rs | 2 +- .../associated-types-overridden-binding.rs | 4 +- ...associated-types-overridden-binding.stderr | 13 ++- .../associated-types-unconstrained.rs | 2 +- .../associated-types-unconstrained.stderr | 2 +- src/test/ui/error-codes/E0283.stderr | 2 +- src/test/ui/error-codes/E0401.rs | 2 +- src/test/ui/error-codes/E0401.stderr | 11 +- src/test/ui/error-codes/E0661.rs | 2 +- src/test/ui/error-codes/E0661.stderr | 9 +- src/test/ui/impl-trait/where-allowed.rs | 6 +- src/test/ui/impl-trait/where-allowed.stderr | 100 ++++++++++-------- src/test/ui/issues/issue-12028.rs | 2 +- src/test/ui/issues/issue-12028.stderr | 2 +- src/test/ui/issues/issue-21974.rs | 2 +- src/test/ui/issues/issue-21974.stderr | 2 +- src/test/ui/issues/issue-24424.rs | 2 +- src/test/ui/issues/issue-24424.stderr | 2 +- src/test/ui/issues/issue-29147.stderr | 2 +- src/test/ui/issues/issue-54954.rs | 4 +- src/test/ui/issues/issue-54954.stderr | 25 ++++- ...method-ambig-one-trait-unknown-int-type.rs | 2 +- src/test/ui/parser/raw/raw-literal-self.rs | 2 +- .../ui/parser/raw/raw-literal-self.stderr | 2 +- .../ui/parser/raw/raw-literal-underscore.rs | 2 +- .../parser/raw/raw-literal-underscore.stderr | 2 +- .../pattern/rest-pat-semantic-disallowed.rs | 1 + .../rest-pat-semantic-disallowed.stderr | 37 ++++--- src/test/ui/question-mark-type-infer.rs | 2 +- src/test/ui/question-mark-type-infer.stderr | 2 +- .../proc-macro-cannot-be-used.rs | 2 +- .../proc-macro-cannot-be-used.stderr | 4 +- .../trait-static-method-generic-inference.rs | 2 +- ...ait-static-method-generic-inference.stderr | 2 +- src/test/ui/type/type-annotation-needed.rs | 2 +- .../ui/type/type-annotation-needed.stderr | 2 +- src/test/ui/type/type-check/issue-40294.rs | 2 +- .../ui/type/type-check/issue-40294.stderr | 2 +- src/test/ui/type/type-path-err-node-types.rs | 2 +- .../ui/type/type-path-err-node-types.stderr | 12 ++- 50 files changed, 256 insertions(+), 160 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index f6b872623d789..1e05018007a8d 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2184,9 +2184,7 @@ impl<'a> LoweringContext<'a> { match decl.output { FunctionRetTy::Ty(ref ty) => match in_band_ty_params { Some((def_id, _)) if impl_trait_return_allow => { - hir::Return(self.lower_ty(ty, - ImplTraitContext::OpaqueTy(Some(def_id)) - )) + hir::Return(self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(def_id)))) } _ => { hir::Return(self.lower_ty(ty, ImplTraitContext::disallowed())) diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index c9fd3392a962d..129cfc8bcb23f 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -988,7 +988,9 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { value.fold_with(&mut BottomUpFolder { tcx, ty_op: |ty| { - if let ty::Opaque(def_id, substs) = ty.sty { + if ty.references_error() { + return tcx.types.err; + } else if let ty::Opaque(def_id, substs) = ty.sty { // Check that this is `impl Trait` type is // declared by `parent_def_id` -- i.e., one whose // value we are inferring. At present, this is @@ -1155,6 +1157,15 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { ); debug!("instantiate_opaque_types: ty_var={:?}", ty_var); + for predicate in &bounds.predicates { + if let ty::Predicate::Projection(projection) = &predicate { + if projection.skip_binder().ty.references_error() { + // No point on adding these obligations since there's a type error involved. + return ty_var; + } + } + } + self.obligations.reserve(bounds.predicates.len()); for predicate in bounds.predicates { // Change the predicate to refer to the type variable, diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index aff866fa76d5f..08fea75739978 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1432,8 +1432,11 @@ impl<'tcx> TyCtxt<'tcx> { } impl<'a, 'tcx> InferCtxt<'a, 'tcx> { - fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>, - body_id: Option) { + fn maybe_report_ambiguity( + &self, + obligation: &PredicateObligation<'tcx>, + body_id: Option, + ) { // Unable to successfully determine, probably means // insufficient type information, but could mean // ambiguous impls. The latter *ought* to be a @@ -1442,9 +1445,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let predicate = self.resolve_vars_if_possible(&obligation.predicate); let span = obligation.cause.span; - debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})", - predicate, - obligation); + debug!( + "maybe_report_ambiguity(predicate={:?}, obligation={:?} body_id={:?}, code={:?})", + predicate, + obligation, + body_id, + obligation.cause.code, + ); // Ambiguity errors are often caused as fallout from earlier // errors. So just ignore them if this infcx is tainted. @@ -1456,6 +1463,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ty::Predicate::Trait(ref data) => { let trait_ref = data.to_poly_trait_ref(); let self_ty = trait_ref.self_ty(); + debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.sty, trait_ref); + if predicate.references_error() { return; } @@ -1480,24 +1489,25 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // be ignoring the fact that we don't KNOW the type works // out. Though even that would probably be harmless, given that // we're only talking about builtin traits, which are known to be - // inhabited. But in any case I just threw in this check for - // has_errors() to be sure that compilation isn't happening - // anyway. In that case, why inundate the user. - if !self.tcx.sess.has_errors() { - if - self.tcx.lang_items().sized_trait() - .map_or(false, |sized_id| sized_id == trait_ref.def_id()) - { - self.need_type_info_err(body_id, span, self_ty).emit(); - } else { - let mut err = struct_span_err!(self.tcx.sess, - span, E0283, - "type annotations required: \ - cannot resolve `{}`", - predicate); - self.note_obligation_cause(&mut err, obligation); - err.emit(); - } + // inhabited. We used to check for `self.tcx.sess.has_errors()` to + // avoid inundating the user with unnecessary errors, but we now + // check upstream for type errors and dont add the obligations to + // begin with in those cases. + if + self.tcx.lang_items().sized_trait() + .map_or(false, |sized_id| sized_id == trait_ref.def_id()) + { + self.need_type_info_err(body_id, span, self_ty).emit(); + } else { + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0283, + "type annotations needed: cannot resolve `{}`", + predicate, + ); + self.note_obligation_cause(&mut err, obligation); + err.emit(); } } @@ -1524,11 +1534,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { _ => { if !self.tcx.sess.has_errors() { - let mut err = struct_span_err!(self.tcx.sess, - obligation.cause.span, E0284, - "type annotations required: \ - cannot resolve `{}`", - predicate); + let mut err = struct_span_err!( + self.tcx.sess, + obligation.cause.span, + E0284, + "type annotations needed: cannot resolve `{}`", + predicate, + ); self.note_obligation_cause(&mut err, obligation); err.emit(); } @@ -1766,7 +1778,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { but not on the corresponding trait method", predicate)); } - ObligationCauseCode::ReturnType(_) | + ObligationCauseCode::ReturnType | + ObligationCauseCode::ReturnValue(_) | ObligationCauseCode::BlockTailExpression(_) => (), ObligationCauseCode::TrivialBound => { err.help("see issue #48214"); diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 1123422ad6008..accbbe3643ea1 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -212,14 +212,14 @@ pub enum ObligationCauseCode<'tcx> { /// Constant expressions must be sized. ConstSized, - /// static items must have `Sync` type + /// Static items must have `Sync` type SharedStatic, BuiltinDerivedObligation(DerivedObligationCause<'tcx>), ImplDerivedObligation(DerivedObligationCause<'tcx>), - /// error derived when matching traits/impls; see ObligationCause for more details + /// Error derived when matching traits/impls; see ObligationCause for more details CompareImplMethodObligation { item_name: ast::Name, impl_item_def_id: DefId, @@ -248,17 +248,20 @@ pub enum ObligationCauseCode<'tcx> { /// `start` has wrong type StartFunctionType, - /// intrinsic has wrong type + /// Intrinsic has wrong type IntrinsicType, - /// method receiver + /// Method receiver MethodReceiver, /// `return` with no expression ReturnNoExpression, /// `return` with an expression - ReturnType(hir::HirId), + ReturnValue(hir::HirId), + + /// Return type of this function + ReturnType, /// Block implicit return BlockTailExpression(hir::HirId), diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index a54bc05f16961..386a5677f5f17 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -214,7 +214,7 @@ pub struct SelectionCache<'tcx> { /// of type variables - it just means the obligation isn't sufficiently /// elaborated. In that case we report an ambiguity, and the caller can /// try again after more type information has been gathered or report a -/// "type annotations required" error. +/// "type annotations needed" error. /// /// However, with type parameters, this can be a real problem - type /// parameters don't unify with regular types, but they *can* unify diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 68c97226f89cf..c0d8230999dd8 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -485,7 +485,8 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { super::TupleInitializerSized => Some(super::TupleInitializerSized), super::StructInitializerSized => Some(super::StructInitializerSized), super::VariableType(id) => Some(super::VariableType(id)), - super::ReturnType(id) => Some(super::ReturnType(id)), + super::ReturnValue(id) => Some(super::ReturnValue(id)), + super::ReturnType => Some(super::ReturnType), super::SizedArgumentType => Some(super::SizedArgumentType), super::SizedReturnType => Some(super::SizedReturnType), super::SizedYieldType => Some(super::SizedYieldType), diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 8bb9648e031ef..525b551b3f2d3 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -438,7 +438,7 @@ bitflags! { /// `true` if there are "names" of types and regions and so forth /// that are local to a particular fn - const HAS_FREE_LOCAL_NAMES = 1 << 9; + const HAS_FREE_LOCAL_NAMES = 1 << 9; /// Present if the type belongs in a local type context. /// Only set for Infer other than Fresh. @@ -446,11 +446,11 @@ bitflags! { /// Does this have any `ReLateBound` regions? Used to check /// if a global bound is safe to evaluate. - const HAS_RE_LATE_BOUND = 1 << 11; + const HAS_RE_LATE_BOUND = 1 << 11; const HAS_TY_PLACEHOLDER = 1 << 12; - const HAS_CT_INFER = 1 << 13; + const HAS_CT_INFER = 1 << 13; const HAS_CT_PLACEHOLDER = 1 << 14; const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits | diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index d98e1f3e1283f..dc536329251ca 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -1253,7 +1253,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { expression.map(|expr| (expr, blk_id)), ); } - ObligationCauseCode::ReturnType(id) => { + ObligationCauseCode::ReturnValue(id) => { db = self.report_return_mismatched_types( cause, expected, found, err, fcx, id, None); } diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index e34a2c6f61c24..550b0f81d2103 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -498,7 +498,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr.span, infer::LateBoundRegionConversionTime::FnCall, &fn_sig.output()).0; - self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType); + if !fn_sig.output().references_error() { + self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType); + } } // We always require that the type provided as the value for @@ -664,12 +666,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ret_ty = ret_coercion.borrow().expected_ty(); let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty.clone()); - ret_coercion.borrow_mut() - .coerce(self, - &self.cause(return_expr.span, - ObligationCauseCode::ReturnType(return_expr.hir_id)), - return_expr, - return_expr_ty); + ret_coercion.borrow_mut().coerce( + self, + &self.cause(return_expr.span, ObligationCauseCode::ReturnValue(return_expr.hir_id)), + return_expr, + return_expr_ty, + ); } /// Type check assignment expression `expr` of form `lhs = rhs`. diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 6c8c5ae512358..b07579327472f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1097,7 +1097,9 @@ fn check_fn<'a, 'tcx>( *fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id); let declared_ret_ty = fn_sig.output(); - fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); + if !declared_ret_ty.references_error() { + fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); + } let revealed_ret_ty = fcx.instantiate_opaque_types_from_value( fn_id, &declared_ret_ty, diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index b0e886a2aa2eb..46b3a3f658927 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -596,7 +596,7 @@ fn check_fn_or_method<'fcx, 'tcx>( } implied_bounds.extend(sig.inputs()); - fcx.register_wf_obligation(sig.output(), span, ObligationCauseCode::MiscObligation); + fcx.register_wf_obligation(sig.output(), span, ObligationCauseCode::ReturnType); // FIXME(#25759) return types should not be implied bounds implied_bounds.push(sig.output()); diff --git a/src/test/ui/associated-types/associated-types-overridden-binding.rs b/src/test/ui/associated-types/associated-types-overridden-binding.rs index fa1889389fd5c..9a64a06c31bad 100644 --- a/src/test/ui/associated-types/associated-types-overridden-binding.rs +++ b/src/test/ui/associated-types/associated-types-overridden-binding.rs @@ -1,10 +1,10 @@ #![feature(trait_alias)] trait Foo: Iterator {} -trait Bar: Foo {} //~ ERROR type annotations required +trait Bar: Foo {} //~ ERROR type annotations needed trait I32Iterator = Iterator; -trait U32Iterator = I32Iterator; +trait U32Iterator = I32Iterator; //~ ERROR type annotations needed fn main() { let _: &dyn I32Iterator; diff --git a/src/test/ui/associated-types/associated-types-overridden-binding.stderr b/src/test/ui/associated-types/associated-types-overridden-binding.stderr index a7238541cd96e..5ef1b23cbcd21 100644 --- a/src/test/ui/associated-types/associated-types-overridden-binding.stderr +++ b/src/test/ui/associated-types/associated-types-overridden-binding.stderr @@ -1,4 +1,4 @@ -error[E0284]: type annotations required: cannot resolve `::Item == i32` +error[E0284]: type annotations needed: cannot resolve `::Item == i32` --> $DIR/associated-types-overridden-binding.rs:4:1 | LL | trait Foo: Iterator {} @@ -6,6 +6,13 @@ LL | trait Foo: Iterator {} LL | trait Bar: Foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0282]: type annotations needed + --> $DIR/associated-types-overridden-binding.rs:7:1 + | +LL | trait U32Iterator = I32Iterator; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0284`. +Some errors have detailed explanations: E0282, E0284. +For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/associated-types/associated-types-unconstrained.rs b/src/test/ui/associated-types/associated-types-unconstrained.rs index 99424836ece2f..b97d4af184f92 100644 --- a/src/test/ui/associated-types/associated-types-unconstrained.rs +++ b/src/test/ui/associated-types/associated-types-unconstrained.rs @@ -12,5 +12,5 @@ impl Foo for isize { pub fn main() { let x: isize = Foo::bar(); - //~^ ERROR type annotations required + //~^ ERROR type annotations needed } diff --git a/src/test/ui/associated-types/associated-types-unconstrained.stderr b/src/test/ui/associated-types/associated-types-unconstrained.stderr index da14a69ae306a..4e9e54d368805 100644 --- a/src/test/ui/associated-types/associated-types-unconstrained.stderr +++ b/src/test/ui/associated-types/associated-types-unconstrained.stderr @@ -1,4 +1,4 @@ -error[E0284]: type annotations required: cannot resolve `<_ as Foo>::A == _` +error[E0284]: type annotations needed: cannot resolve `<_ as Foo>::A == _` --> $DIR/associated-types-unconstrained.rs:14:20 | LL | let x: isize = Foo::bar(); diff --git a/src/test/ui/error-codes/E0283.stderr b/src/test/ui/error-codes/E0283.stderr index 1d99f99c62383..aba649d83ec01 100644 --- a/src/test/ui/error-codes/E0283.stderr +++ b/src/test/ui/error-codes/E0283.stderr @@ -1,4 +1,4 @@ -error[E0283]: type annotations required: cannot resolve `_: Generator` +error[E0283]: type annotations needed: cannot resolve `_: Generator` --> $DIR/E0283.rs:18:21 | LL | fn create() -> u32; diff --git a/src/test/ui/error-codes/E0401.rs b/src/test/ui/error-codes/E0401.rs index a120198b7284d..c30e5f4718871 100644 --- a/src/test/ui/error-codes/E0401.rs +++ b/src/test/ui/error-codes/E0401.rs @@ -8,7 +8,7 @@ fn foo(x: T) { W: Fn()> (y: T) { //~ ERROR E0401 } - bfnr(x); + bfnr(x); //~ ERROR type annotations needed } diff --git a/src/test/ui/error-codes/E0401.stderr b/src/test/ui/error-codes/E0401.stderr index 1d9dfe46722ec..485b76a09a3c4 100644 --- a/src/test/ui/error-codes/E0401.stderr +++ b/src/test/ui/error-codes/E0401.stderr @@ -32,6 +32,13 @@ LL | fn helper(sel: &Self) -> u8 { | use of generic parameter from outer function | use a type here instead -error: aborting due to 3 previous errors +error[E0282]: type annotations needed + --> $DIR/E0401.rs:11:5 + | +LL | bfnr(x); + | ^^^^ cannot infer type for `U` + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0401`. +Some errors have detailed explanations: E0282, E0401. +For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/error-codes/E0661.rs b/src/test/ui/error-codes/E0661.rs index 2440e3a446eb4..5ac0c415ae1b2 100644 --- a/src/test/ui/error-codes/E0661.rs +++ b/src/test/ui/error-codes/E0661.rs @@ -3,7 +3,7 @@ #![feature(asm)] fn main() { - let a; + let a; //~ ERROR type annotations needed asm!("nop" : "r"(a)); //~^ ERROR E0661 } diff --git a/src/test/ui/error-codes/E0661.stderr b/src/test/ui/error-codes/E0661.stderr index 58f7e7fa0f919..3537e0bc3a4c6 100644 --- a/src/test/ui/error-codes/E0661.stderr +++ b/src/test/ui/error-codes/E0661.stderr @@ -4,5 +4,12 @@ error[E0661]: output operand constraint lacks '=' or '+' LL | asm!("nop" : "r"(a)); | ^^^ -error: aborting due to previous error +error[E0282]: type annotations needed + --> $DIR/E0661.rs:6:9 + | +LL | let a; + | ^ consider giving `a` a type + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/impl-trait/where-allowed.rs b/src/test/ui/impl-trait/where-allowed.rs index 9eac6b714de37..65c4b78bf6a40 100644 --- a/src/test/ui/impl-trait/where-allowed.rs +++ b/src/test/ui/impl-trait/where-allowed.rs @@ -11,8 +11,9 @@ fn in_return() -> impl Debug { panic!() } // Allowed fn in_adt_in_parameters(_: Vec) { panic!() } -// Allowed +// Disallowed fn in_adt_in_return() -> Vec { panic!() } +//~^ ERROR type annotations needed // Disallowed fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() } @@ -58,7 +59,8 @@ fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } // Disallowed fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } //~^ ERROR `impl Trait` not allowed outside of function and inherent method return types -//~^^ ERROR nested `impl Trait` is not allowed +//~| ERROR nested `impl Trait` is not allowed +//~| ERROR type annotations needed // Disallowed fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() } diff --git a/src/test/ui/impl-trait/where-allowed.stderr b/src/test/ui/impl-trait/where-allowed.stderr index 1332fff84f50a..dfb6e6524d9a5 100644 --- a/src/test/ui/impl-trait/where-allowed.stderr +++ b/src/test/ui/impl-trait/where-allowed.stderr @@ -1,5 +1,5 @@ error[E0666]: nested `impl Trait` is not allowed - --> $DIR/where-allowed.rs:50:51 + --> $DIR/where-allowed.rs:51:51 | LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | --------^^^^^^^^^^- @@ -8,7 +8,7 @@ LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed - --> $DIR/where-allowed.rs:59:57 + --> $DIR/where-allowed.rs:60:57 | LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } | --------^^^^^^^^^^- @@ -17,7 +17,7 @@ LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic | outer `impl Trait` error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/where-allowed.rs:122:5 + --> $DIR/where-allowed.rs:124:5 | LL | type Out = impl Debug; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | type Out = impl Debug; = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/where-allowed.rs:158:1 + --> $DIR/where-allowed.rs:160:1 | LL | type InTypeAlias = impl Debug; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -35,205 +35,205 @@ LL | type InTypeAlias = impl Debug; = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:18:40 + --> $DIR/where-allowed.rs:19:40 | LL | fn in_fn_parameter_in_parameters(_: fn(impl Debug)) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:22:42 + --> $DIR/where-allowed.rs:23:42 | LL | fn in_fn_return_in_parameters(_: fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:26:38 + --> $DIR/where-allowed.rs:27:38 | LL | fn in_fn_parameter_in_return() -> fn(impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:30:40 + --> $DIR/where-allowed.rs:31:40 | LL | fn in_fn_return_in_return() -> fn() -> impl Debug { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:34:49 + --> $DIR/where-allowed.rs:35:49 | LL | fn in_dyn_Fn_parameter_in_parameters(_: &dyn Fn(impl Debug)) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:38:51 + --> $DIR/where-allowed.rs:39:51 | LL | fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:42:55 + --> $DIR/where-allowed.rs:43:55 | LL | fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:46:57 + --> $DIR/where-allowed.rs:47:57 | LL | fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:50:51 + --> $DIR/where-allowed.rs:51:51 | LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:55:53 + --> $DIR/where-allowed.rs:56:53 | LL | fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:59:57 + --> $DIR/where-allowed.rs:60:57 | LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:64:59 + --> $DIR/where-allowed.rs:66:59 | LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:68:38 + --> $DIR/where-allowed.rs:70:38 | LL | fn in_Fn_parameter_in_generics (_: F) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:72:40 + --> $DIR/where-allowed.rs:74:40 | LL | fn in_Fn_return_in_generics impl Debug> (_: F) { panic!() } | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:85:32 + --> $DIR/where-allowed.rs:87:32 | LL | struct InBraceStructField { x: impl Debug } | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:89:41 + --> $DIR/where-allowed.rs:91:41 | LL | struct InAdtInBraceStructField { x: Vec } | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:93:27 + --> $DIR/where-allowed.rs:95:27 | LL | struct InTupleStructField(impl Debug); | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:98:25 + --> $DIR/where-allowed.rs:100:25 | LL | InBraceVariant { x: impl Debug }, | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:100:20 + --> $DIR/where-allowed.rs:102:20 | LL | InTupleVariant(impl Debug), | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:111:23 + --> $DIR/where-allowed.rs:113:23 | LL | fn in_return() -> impl Debug; | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:129:34 + --> $DIR/where-allowed.rs:131:34 | LL | fn in_trait_impl_return() -> impl Debug { () } | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:142:33 + --> $DIR/where-allowed.rs:144:33 | LL | fn in_foreign_parameters(_: impl Debug); | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:145:31 + --> $DIR/where-allowed.rs:147:31 | LL | fn in_foreign_return() -> impl Debug; | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:162:39 + --> $DIR/where-allowed.rs:164:39 | LL | type InReturnInTypeAlias = fn() -> impl Debug; | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:166:16 + --> $DIR/where-allowed.rs:168:16 | LL | impl PartialEq for () { | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:171:24 + --> $DIR/where-allowed.rs:173:24 | LL | impl PartialEq<()> for impl Debug { | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:176:6 + --> $DIR/where-allowed.rs:178:6 | LL | impl impl Debug { | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:182:24 + --> $DIR/where-allowed.rs:184:24 | LL | impl InInherentImplAdt { | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:188:11 + --> $DIR/where-allowed.rs:190:11 | LL | where impl Debug: Debug | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:195:15 + --> $DIR/where-allowed.rs:197:15 | LL | where Vec: Debug | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:202:24 + --> $DIR/where-allowed.rs:204:24 | LL | where T: PartialEq | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:209:17 + --> $DIR/where-allowed.rs:211:17 | LL | where T: Fn(impl Debug) | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:216:22 + --> $DIR/where-allowed.rs:218:22 | LL | where T: Fn() -> impl Debug | ^^^^^^^^^^ error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:222:29 + --> $DIR/where-allowed.rs:224:29 | LL | let _in_local_variable: impl Fn() = || {}; | ^^^^^^^^^ @@ -241,24 +241,36 @@ LL | let _in_local_variable: impl Fn() = || {}; = help: add `#![feature(impl_trait_in_bindings)]` to the crate attributes to enable error[E0562]: `impl Trait` not allowed outside of function and inherent method return types - --> $DIR/where-allowed.rs:224:46 + --> $DIR/where-allowed.rs:226:46 | LL | let _in_return_in_local_variable = || -> impl Fn() { || {} }; | ^^^^^^^^^ +error[E0282]: type annotations needed + --> $DIR/where-allowed.rs:15:30 + | +LL | fn in_adt_in_return() -> Vec { panic!() } + | ^^^^^^^^^^ cannot infer type + +error[E0282]: type annotations needed + --> $DIR/where-allowed.rs:60:49 + | +LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } + | ^^^^^^^^^^^^^^^^^^^ cannot infer type + error: could not find defining uses - --> $DIR/where-allowed.rs:158:1 + --> $DIR/where-allowed.rs:160:1 | LL | type InTypeAlias = impl Debug; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: could not find defining uses - --> $DIR/where-allowed.rs:122:5 + --> $DIR/where-allowed.rs:124:5 | LL | type Out = impl Debug; | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 41 previous errors +error: aborting due to 43 previous errors -Some errors have detailed explanations: E0562, E0658. -For more information about an error, try `rustc --explain E0562`. +Some errors have detailed explanations: E0282, E0562, E0658. +For more information about an error, try `rustc --explain E0282`. diff --git a/src/test/ui/issues/issue-12028.rs b/src/test/ui/issues/issue-12028.rs index 7c2b0d69c8b25..7503766ff2084 100644 --- a/src/test/ui/issues/issue-12028.rs +++ b/src/test/ui/issues/issue-12028.rs @@ -24,7 +24,7 @@ trait StreamHash: Hash { impl Hash for u8 { fn hash2(&self, hasher: &H) -> u64 { let mut stream = hasher.stream(); - self.input_stream(&mut stream); //~ ERROR type annotations required + self.input_stream(&mut stream); //~ ERROR type annotations needed Stream::result(&stream) } } diff --git a/src/test/ui/issues/issue-12028.stderr b/src/test/ui/issues/issue-12028.stderr index 24aa88c3fa379..ff92d01a69ed2 100644 --- a/src/test/ui/issues/issue-12028.stderr +++ b/src/test/ui/issues/issue-12028.stderr @@ -1,4 +1,4 @@ -error[E0284]: type annotations required: cannot resolve `<_ as StreamHasher>::S == ::S` +error[E0284]: type annotations needed: cannot resolve `<_ as StreamHasher>::S == ::S` --> $DIR/issue-12028.rs:27:14 | LL | self.input_stream(&mut stream); diff --git a/src/test/ui/issues/issue-21974.rs b/src/test/ui/issues/issue-21974.rs index f49eb230b4083..0cbe38d6ec0b6 100644 --- a/src/test/ui/issues/issue-21974.rs +++ b/src/test/ui/issues/issue-21974.rs @@ -7,7 +7,7 @@ trait Foo { fn foo(self); } -fn foo<'a,'b,T>(x: &'a T, y: &'b T) //~ ERROR type annotations required +fn foo<'a,'b,T>(x: &'a T, y: &'b T) //~ ERROR type annotations needed where &'a T : Foo, &'b T : Foo { diff --git a/src/test/ui/issues/issue-21974.stderr b/src/test/ui/issues/issue-21974.stderr index a6cce7846e81d..7ceb2bd23f6cd 100644 --- a/src/test/ui/issues/issue-21974.stderr +++ b/src/test/ui/issues/issue-21974.stderr @@ -1,4 +1,4 @@ -error[E0283]: type annotations required: cannot resolve `&'a T: Foo` +error[E0283]: type annotations needed: cannot resolve `&'a T: Foo` --> $DIR/issue-21974.rs:10:1 | LL | trait Foo { diff --git a/src/test/ui/issues/issue-24424.rs b/src/test/ui/issues/issue-24424.rs index 8b8c5bc23e48b..9b74cd1230e8a 100644 --- a/src/test/ui/issues/issue-24424.rs +++ b/src/test/ui/issues/issue-24424.rs @@ -2,6 +2,6 @@ trait Trait1<'l0, T0> {} trait Trait0<'l0> {} impl <'l0, 'l1, T0> Trait1<'l0, T0> for bool where T0 : Trait0<'l0>, T0 : Trait0<'l1> {} -//~^ ERROR type annotations required: cannot resolve `T0: Trait0<'l0>` +//~^ ERROR type annotations needed: cannot resolve `T0: Trait0<'l0>` fn main() {} diff --git a/src/test/ui/issues/issue-24424.stderr b/src/test/ui/issues/issue-24424.stderr index 7ff019a30a864..8c539f7cedd19 100644 --- a/src/test/ui/issues/issue-24424.stderr +++ b/src/test/ui/issues/issue-24424.stderr @@ -1,4 +1,4 @@ -error[E0283]: type annotations required: cannot resolve `T0: Trait0<'l0>` +error[E0283]: type annotations needed: cannot resolve `T0: Trait0<'l0>` --> $DIR/issue-24424.rs:4:1 | LL | trait Trait0<'l0> {} diff --git a/src/test/ui/issues/issue-29147.stderr b/src/test/ui/issues/issue-29147.stderr index 0dc9b0c9e10cd..c9dd92fca7dc8 100644 --- a/src/test/ui/issues/issue-29147.stderr +++ b/src/test/ui/issues/issue-29147.stderr @@ -1,4 +1,4 @@ -error[E0283]: type annotations required: cannot resolve `S5<_>: Foo` +error[E0283]: type annotations needed: cannot resolve `S5<_>: Foo` --> $DIR/issue-29147.rs:21:13 | LL | trait Foo { fn xxx(&self); } diff --git a/src/test/ui/issues/issue-54954.rs b/src/test/ui/issues/issue-54954.rs index 40045bc758cff..9e9f92ed9ace5 100644 --- a/src/test/ui/issues/issue-54954.rs +++ b/src/test/ui/issues/issue-54954.rs @@ -1,7 +1,7 @@ #![feature(const_fn)] const ARR_LEN: usize = Tt::const_val::<[i8; 123]>(); -//~^ ERROR constant contains unimplemented expression type +//~^ ERROR type annotations needed trait Tt { const fn const_val() -> usize { @@ -11,6 +11,8 @@ trait Tt { } fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] { + //~^ ERROR evaluation of constant value failed + //~| ERROR evaluation of constant value failed z } diff --git a/src/test/ui/issues/issue-54954.stderr b/src/test/ui/issues/issue-54954.stderr index 29edb506c4b1c..82315c125798f 100644 --- a/src/test/ui/issues/issue-54954.stderr +++ b/src/test/ui/issues/issue-54954.stderr @@ -4,13 +4,28 @@ error[E0379]: trait fns cannot be declared const LL | const fn const_val() -> usize { | ^^^^^ trait fns cannot be const -error[E0019]: constant contains unimplemented expression type +error[E0283]: type annotations needed: cannot resolve `_: Tt` --> $DIR/issue-54954.rs:3:24 | LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | const fn const_val() -> usize { + | --------------------------------------- required by `Tt::const_val` + +error[E0080]: evaluation of constant value failed + --> $DIR/issue-54954.rs:13:15 + | +LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] { + | ^^^^^^^ referenced constant has errors + +error[E0080]: evaluation of constant value failed + --> $DIR/issue-54954.rs:13:34 + | +LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] { + | ^^^^^^^ referenced constant has errors -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0019, E0379. -For more information about an error, try `rustc --explain E0019`. +Some errors have detailed explanations: E0080, E0283, E0379. +For more information about an error, try `rustc --explain E0080`. diff --git a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs index e33f23c64dbe1..49fe7d1324ca8 100644 --- a/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs +++ b/src/test/ui/methods/method-ambig-one-trait-unknown-int-type.rs @@ -15,7 +15,7 @@ impl Foo for Vec { } // This is very hokey: we have heuristics to suppress messages about -// type annotations required. But placing these two bits of code into +// type annotations needed. But placing these two bits of code into // distinct functions, in this order, causes us to print out both // errors I'd like to see. diff --git a/src/test/ui/parser/raw/raw-literal-self.rs b/src/test/ui/parser/raw/raw-literal-self.rs index 123a11b6f8543..a0c9e24c235d6 100644 --- a/src/test/ui/parser/raw/raw-literal-self.rs +++ b/src/test/ui/parser/raw/raw-literal-self.rs @@ -1,4 +1,4 @@ fn main() { - let r#self; + let r#self: (); //~^ ERROR `self` cannot be a raw identifier } diff --git a/src/test/ui/parser/raw/raw-literal-self.stderr b/src/test/ui/parser/raw/raw-literal-self.stderr index 9a330fcdf2aae..2a40dfe200cde 100644 --- a/src/test/ui/parser/raw/raw-literal-self.stderr +++ b/src/test/ui/parser/raw/raw-literal-self.stderr @@ -1,7 +1,7 @@ error: `self` cannot be a raw identifier --> $DIR/raw-literal-self.rs:2:9 | -LL | let r#self; +LL | let r#self: (); | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/raw/raw-literal-underscore.rs b/src/test/ui/parser/raw/raw-literal-underscore.rs index 6d15f1e7f0afd..a9d9e13a9d9ec 100644 --- a/src/test/ui/parser/raw/raw-literal-underscore.rs +++ b/src/test/ui/parser/raw/raw-literal-underscore.rs @@ -1,4 +1,4 @@ fn main() { - let r#_; + let r#_: (); //~^ ERROR `_` cannot be a raw identifier } diff --git a/src/test/ui/parser/raw/raw-literal-underscore.stderr b/src/test/ui/parser/raw/raw-literal-underscore.stderr index d96b14f55a39b..d7a364d8579ef 100644 --- a/src/test/ui/parser/raw/raw-literal-underscore.stderr +++ b/src/test/ui/parser/raw/raw-literal-underscore.stderr @@ -1,7 +1,7 @@ error: `_` cannot be a raw identifier --> $DIR/raw-literal-underscore.rs:2:9 | -LL | let r#_; +LL | let r#_: (); | ^^^ error: aborting due to previous error diff --git a/src/test/ui/pattern/rest-pat-semantic-disallowed.rs b/src/test/ui/pattern/rest-pat-semantic-disallowed.rs index 36a45a3ccdc4b..31620216e82e1 100644 --- a/src/test/ui/pattern/rest-pat-semantic-disallowed.rs +++ b/src/test/ui/pattern/rest-pat-semantic-disallowed.rs @@ -31,6 +31,7 @@ fn rest_patterns() { // Ident patterns: let x @ ..; //~ ERROR `..` patterns are not allowed here + //~^ ERROR type annotations needed let ref x @ ..; //~ ERROR `..` patterns are not allowed here let ref mut x @ ..; //~ ERROR `..` patterns are not allowed here diff --git a/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr b/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr index 826f76b356cf1..be484e3a4d417 100644 --- a/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr +++ b/src/test/ui/pattern/rest-pat-semantic-disallowed.stderr @@ -58,7 +58,7 @@ LL | let x @ ..; = note: only allowed in tuple, tuple struct, and slice patterns error: `..` patterns are not allowed here - --> $DIR/rest-pat-semantic-disallowed.rs:34:17 + --> $DIR/rest-pat-semantic-disallowed.rs:35:17 | LL | let ref x @ ..; | ^^ @@ -66,7 +66,7 @@ LL | let ref x @ ..; = note: only allowed in tuple, tuple struct, and slice patterns error: `..` patterns are not allowed here - --> $DIR/rest-pat-semantic-disallowed.rs:35:21 + --> $DIR/rest-pat-semantic-disallowed.rs:36:21 | LL | let ref mut x @ ..; | ^^ @@ -74,7 +74,7 @@ LL | let ref mut x @ ..; = note: only allowed in tuple, tuple struct, and slice patterns error: `..` can only be used once per tuple pattern - --> $DIR/rest-pat-semantic-disallowed.rs:42:9 + --> $DIR/rest-pat-semantic-disallowed.rs:43:9 | LL | .., | -- previously used here @@ -82,7 +82,7 @@ LL | .., | ^^ can only be used once per tuple pattern error: `..` can only be used once per tuple pattern - --> $DIR/rest-pat-semantic-disallowed.rs:43:9 + --> $DIR/rest-pat-semantic-disallowed.rs:44:9 | LL | .., | -- previously used here @@ -91,7 +91,7 @@ LL | .. | ^^ can only be used once per tuple pattern error: `..` can only be used once per tuple pattern - --> $DIR/rest-pat-semantic-disallowed.rs:48:9 + --> $DIR/rest-pat-semantic-disallowed.rs:49:9 | LL | .., | -- previously used here @@ -100,7 +100,7 @@ LL | .. | ^^ can only be used once per tuple pattern error: `..` can only be used once per tuple struct pattern - --> $DIR/rest-pat-semantic-disallowed.rs:58:9 + --> $DIR/rest-pat-semantic-disallowed.rs:59:9 | LL | .., | -- previously used here @@ -108,7 +108,7 @@ LL | .., | ^^ can only be used once per tuple struct pattern error: `..` can only be used once per tuple struct pattern - --> $DIR/rest-pat-semantic-disallowed.rs:59:9 + --> $DIR/rest-pat-semantic-disallowed.rs:60:9 | LL | .., | -- previously used here @@ -117,7 +117,7 @@ LL | .. | ^^ can only be used once per tuple struct pattern error: `..` can only be used once per tuple struct pattern - --> $DIR/rest-pat-semantic-disallowed.rs:64:9 + --> $DIR/rest-pat-semantic-disallowed.rs:65:9 | LL | .., | -- previously used here @@ -126,7 +126,7 @@ LL | .. | ^^ can only be used once per tuple struct pattern error: `..` can only be used once per slice pattern - --> $DIR/rest-pat-semantic-disallowed.rs:72:9 + --> $DIR/rest-pat-semantic-disallowed.rs:73:9 | LL | .., | -- previously used here @@ -134,7 +134,7 @@ LL | .., | ^^ can only be used once per slice pattern error: `..` can only be used once per slice pattern - --> $DIR/rest-pat-semantic-disallowed.rs:73:9 + --> $DIR/rest-pat-semantic-disallowed.rs:74:9 | LL | .., | -- previously used here @@ -143,7 +143,7 @@ LL | .. | ^^ can only be used once per slice pattern error: `..` can only be used once per slice pattern - --> $DIR/rest-pat-semantic-disallowed.rs:77:17 + --> $DIR/rest-pat-semantic-disallowed.rs:78:17 | LL | .., | -- previously used here @@ -151,7 +151,7 @@ LL | ref x @ .., | ^^ can only be used once per slice pattern error: `..` can only be used once per slice pattern - --> $DIR/rest-pat-semantic-disallowed.rs:78:21 + --> $DIR/rest-pat-semantic-disallowed.rs:79:21 | LL | .., | -- previously used here @@ -160,7 +160,7 @@ LL | ref mut y @ .., | ^^ can only be used once per slice pattern error: `..` patterns are not allowed here - --> $DIR/rest-pat-semantic-disallowed.rs:79:18 + --> $DIR/rest-pat-semantic-disallowed.rs:80:18 | LL | (ref z @ ..), | ^^ @@ -168,7 +168,7 @@ LL | (ref z @ ..), = note: only allowed in tuple, tuple struct, and slice patterns error: `..` can only be used once per slice pattern - --> $DIR/rest-pat-semantic-disallowed.rs:80:9 + --> $DIR/rest-pat-semantic-disallowed.rs:81:9 | LL | .., | -- previously used here @@ -184,5 +184,12 @@ LL | fn foo(..: u8) {} | = note: only allowed in tuple, tuple struct, and slice patterns -error: aborting due to 22 previous errors +error[E0282]: type annotations needed + --> $DIR/rest-pat-semantic-disallowed.rs:33:9 + | +LL | let x @ ..; + | ^^^^^^ consider giving this pattern a type + +error: aborting due to 23 previous errors +For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/question-mark-type-infer.rs b/src/test/ui/question-mark-type-infer.rs index 2e7a342b95e17..95ee01a70cead 100644 --- a/src/test/ui/question-mark-type-infer.rs +++ b/src/test/ui/question-mark-type-infer.rs @@ -9,7 +9,7 @@ fn f(x: &i32) -> Result { fn g() -> Result, ()> { let l = [1, 2, 3, 4]; - l.iter().map(f).collect()? //~ ERROR type annotations required: cannot resolve + l.iter().map(f).collect()? //~ ERROR type annotations needed: cannot resolve } fn main() { diff --git a/src/test/ui/question-mark-type-infer.stderr b/src/test/ui/question-mark-type-infer.stderr index f62a540572c93..53a170e7d431c 100644 --- a/src/test/ui/question-mark-type-infer.stderr +++ b/src/test/ui/question-mark-type-infer.stderr @@ -1,4 +1,4 @@ -error[E0284]: type annotations required: cannot resolve `<_ as std::ops::Try>::Ok == _` +error[E0284]: type annotations needed: cannot resolve `<_ as std::ops::Try>::Ok == _` --> $DIR/question-mark-type-infer.rs:12:5 | LL | l.iter().map(f).collect()? diff --git a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs index 9f4e2710dc420..e2680446f851a 100644 --- a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs +++ b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.rs @@ -20,7 +20,7 @@ type Alias = extern "C" fn(#[id] u8, #[id] ...); fn free(#[id] arg1: u8) { //~^ ERROR expected an inert attribute, found an attribute macro - let lam = |#[id] W(x), #[id] y| (); + let lam = |#[id] W(x), #[id] y: usize| (); //~^ ERROR expected an inert attribute, found an attribute macro //~| ERROR expected an inert attribute, found an attribute macro } diff --git a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr index b4946fa74943f..4654dc1b496f2 100644 --- a/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr +++ b/src/test/ui/rfc-2565-param-attrs/proc-macro-cannot-be-used.stderr @@ -37,13 +37,13 @@ LL | fn free(#[id] arg1: u8) { error: expected an inert attribute, found an attribute macro --> $DIR/proc-macro-cannot-be-used.rs:23:16 | -LL | let lam = |#[id] W(x), #[id] y| (); +LL | let lam = |#[id] W(x), #[id] y: usize| (); | ^^^^^ error: expected an inert attribute, found an attribute macro --> $DIR/proc-macro-cannot-be-used.rs:23:28 | -LL | let lam = |#[id] W(x), #[id] y| (); +LL | let lam = |#[id] W(x), #[id] y: usize| (); | ^^^^^ error: expected an inert attribute, found an attribute macro diff --git a/src/test/ui/traits/trait-static-method-generic-inference.rs b/src/test/ui/traits/trait-static-method-generic-inference.rs index c08bd5cb13566..759416d1901db 100644 --- a/src/test/ui/traits/trait-static-method-generic-inference.rs +++ b/src/test/ui/traits/trait-static-method-generic-inference.rs @@ -22,7 +22,7 @@ mod base { pub fn foo() { let _f: base::Foo = base::HasNew::new(); - //~^ ERROR type annotations required + //~^ ERROR type annotations needed } fn main() { } diff --git a/src/test/ui/traits/trait-static-method-generic-inference.stderr b/src/test/ui/traits/trait-static-method-generic-inference.stderr index a99536d31ef84..22931c5ba32e9 100644 --- a/src/test/ui/traits/trait-static-method-generic-inference.stderr +++ b/src/test/ui/traits/trait-static-method-generic-inference.stderr @@ -1,4 +1,4 @@ -error[E0283]: type annotations required: cannot resolve `_: base::HasNew` +error[E0283]: type annotations needed: cannot resolve `_: base::HasNew` --> $DIR/trait-static-method-generic-inference.rs:24:25 | LL | fn new() -> T; diff --git a/src/test/ui/type/type-annotation-needed.rs b/src/test/ui/type/type-annotation-needed.rs index ddf16f7699517..3b1521d5c028b 100644 --- a/src/test/ui/type/type-annotation-needed.rs +++ b/src/test/ui/type/type-annotation-needed.rs @@ -4,5 +4,5 @@ fn foo>(x: i32) {} fn main() { foo(42); - //~^ ERROR type annotations required + //~^ ERROR type annotations needed } diff --git a/src/test/ui/type/type-annotation-needed.stderr b/src/test/ui/type/type-annotation-needed.stderr index 01287b727d2f8..460bbe9dbc4f9 100644 --- a/src/test/ui/type/type-annotation-needed.stderr +++ b/src/test/ui/type/type-annotation-needed.stderr @@ -1,4 +1,4 @@ -error[E0283]: type annotations required: cannot resolve `_: std::convert::Into` +error[E0283]: type annotations needed: cannot resolve `_: std::convert::Into` --> $DIR/type-annotation-needed.rs:6:5 | LL | fn foo>(x: i32) {} diff --git a/src/test/ui/type/type-check/issue-40294.rs b/src/test/ui/type/type-check/issue-40294.rs index c73acdc467ee2..7e6429ccfbe30 100644 --- a/src/test/ui/type/type-check/issue-40294.rs +++ b/src/test/ui/type/type-check/issue-40294.rs @@ -2,7 +2,7 @@ trait Foo: Sized { fn foo(self); } -fn foo<'a,'b,T>(x: &'a T, y: &'b T) //~ ERROR type annotations required +fn foo<'a,'b,T>(x: &'a T, y: &'b T) //~ ERROR type annotations needed where &'a T : Foo, &'b T : Foo { diff --git a/src/test/ui/type/type-check/issue-40294.stderr b/src/test/ui/type/type-check/issue-40294.stderr index 732a81c8a244a..508783aaf2b0e 100644 --- a/src/test/ui/type/type-check/issue-40294.stderr +++ b/src/test/ui/type/type-check/issue-40294.stderr @@ -1,4 +1,4 @@ -error[E0283]: type annotations required: cannot resolve `&'a T: Foo` +error[E0283]: type annotations needed: cannot resolve `&'a T: Foo` --> $DIR/issue-40294.rs:5:1 | LL | trait Foo: Sized { diff --git a/src/test/ui/type/type-path-err-node-types.rs b/src/test/ui/type/type-path-err-node-types.rs index a2cc5070db482..15adfebb33400 100644 --- a/src/test/ui/type/type-path-err-node-types.rs +++ b/src/test/ui/type/type-path-err-node-types.rs @@ -20,7 +20,7 @@ fn method() { } fn closure() { - let _ = |a, b: _| -> _ { 0 }; // OK + let _ = |a, b: _| -> _ { 0 }; //~ ERROR type annotations needed } fn main() {} diff --git a/src/test/ui/type/type-path-err-node-types.stderr b/src/test/ui/type/type-path-err-node-types.stderr index ed744478f26f8..cd93525c76219 100644 --- a/src/test/ui/type/type-path-err-node-types.stderr +++ b/src/test/ui/type/type-path-err-node-types.stderr @@ -22,7 +22,13 @@ error[E0425]: cannot find value `nonexistent` in this scope LL | nonexistent.nonexistent::(); | ^^^^^^^^^^^ not found in this scope -error: aborting due to 4 previous errors +error[E0282]: type annotations needed + --> $DIR/type-path-err-node-types.rs:23:14 + | +LL | let _ = |a, b: _| -> _ { 0 }; + | ^ consider giving this closure parameter a type + +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0412, E0425, E0433. -For more information about an error, try `rustc --explain E0412`. +Some errors have detailed explanations: E0282, E0412, E0425, E0433. +For more information about an error, try `rustc --explain E0282`. From affa038c293a1b2b38cc8d323a652c1c279b9391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 24 Sep 2019 11:28:30 -0700 Subject: [PATCH 160/413] clean up, push silencing logic to more relevant places --- src/librustc_typeck/check/expr.rs | 4 +- src/librustc_typeck/check/mod.rs | 86 +++++++++++++++++-------------- 2 files changed, 49 insertions(+), 41 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 550b0f81d2103..6b694bfc8da25 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -498,9 +498,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr.span, infer::LateBoundRegionConversionTime::FnCall, &fn_sig.output()).0; - if !fn_sig.output().references_error() { - self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType); - } + self.require_type_is_sized_deferred(output, expr.span, traits::SizedReturnType); } // We always require that the type provided as the value for diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b07579327472f..02f4f2a3744c6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1097,9 +1097,7 @@ fn check_fn<'a, 'tcx>( *fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id); let declared_ret_ty = fn_sig.output(); - if !declared_ret_ty.references_error() { - fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); - } + fcx.require_type_is_sized(declared_ret_ty, decl.output.span(), traits::SizedReturnType); let revealed_ret_ty = fcx.instantiate_opaque_types_from_value( fn_id, &declared_ret_ty, @@ -2700,30 +2698,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { traits::ObligationCause::new(span, self.body_id, code)); } - pub fn require_type_is_sized(&self, - ty: Ty<'tcx>, - span: Span, - code: traits::ObligationCauseCode<'tcx>) - { - let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); - self.require_type_meets(ty, span, code, lang_item); + pub fn require_type_is_sized( + &self, + ty: Ty<'tcx>, + span: Span, + code: traits::ObligationCauseCode<'tcx>, + ) { + if !ty.references_error() { + let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); + self.require_type_meets(ty, span, code, lang_item); + } } - pub fn require_type_is_sized_deferred(&self, - ty: Ty<'tcx>, - span: Span, - code: traits::ObligationCauseCode<'tcx>) - { - self.deferred_sized_obligations.borrow_mut().push((ty, span, code)); + pub fn require_type_is_sized_deferred( + &self, + ty: Ty<'tcx>, + span: Span, + code: traits::ObligationCauseCode<'tcx>, + ) { + if !ty.references_error() { + self.deferred_sized_obligations.borrow_mut().push((ty, span, code)); + } } - pub fn register_bound(&self, - ty: Ty<'tcx>, - def_id: DefId, - cause: traits::ObligationCause<'tcx>) - { - self.fulfillment_cx.borrow_mut() - .register_bound(self, self.param_env, ty, def_id, cause); + pub fn register_bound( + &self, + ty: Ty<'tcx>, + def_id: DefId, + cause: traits::ObligationCause<'tcx>, + ) { + if !ty.references_error() { + self.fulfillment_cx.borrow_mut() + .register_bound(self, self.param_env, ty, def_id, cause); + } } pub fn to_ty(&self, ast_t: &hir::Ty) -> Ty<'tcx> { @@ -2782,22 +2789,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Registers an obligation for checking later, during regionck, that the type `ty` must /// outlive the region `r`. - pub fn register_wf_obligation(&self, - ty: Ty<'tcx>, - span: Span, - code: traits::ObligationCauseCode<'tcx>) - { + pub fn register_wf_obligation( + &self, + ty: Ty<'tcx>, + span: Span, + code: traits::ObligationCauseCode<'tcx>, + ) { // WF obligations never themselves fail, so no real need to give a detailed cause: let cause = traits::ObligationCause::new(span, self.body_id, code); - self.register_predicate(traits::Obligation::new(cause, - self.param_env, - ty::Predicate::WellFormed(ty))); + self.register_predicate( + traits::Obligation::new(cause, self.param_env, ty::Predicate::WellFormed(ty)), + ); } /// Registers obligations that all types appearing in `substs` are well-formed. pub fn add_wf_bounds(&self, substs: SubstsRef<'tcx>, expr: &hir::Expr) { for ty in substs.types() { - self.register_wf_obligation(ty, expr.span, traits::MiscObligation); + if !ty.references_error() { + self.register_wf_obligation(ty, expr.span, traits::MiscObligation); + } } } @@ -2836,12 +2846,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME(arielb1): use this instead of field.ty everywhere // Only for fields! Returns for methods> // Indifferent to privacy flags - pub fn field_ty(&self, - span: Span, - field: &'tcx ty::FieldDef, - substs: SubstsRef<'tcx>) - -> Ty<'tcx> - { + pub fn field_ty( + &self, + span: Span, + field: &'tcx ty::FieldDef, + substs: SubstsRef<'tcx>, + ) -> Ty<'tcx> { self.normalize_associated_types_in(span, &field.ty(self.tcx, substs)) } From b7ca1c5a1e349edebae2ca4a2525dc6ecf04f17d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 24 Sep 2019 11:55:53 -0700 Subject: [PATCH 161/413] fix rebase --- src/test/ui/issues/issue-54954.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/issues/issue-54954.stderr b/src/test/ui/issues/issue-54954.stderr index 82315c125798f..56ccdaf7aac40 100644 --- a/src/test/ui/issues/issue-54954.stderr +++ b/src/test/ui/issues/issue-54954.stderr @@ -11,7 +11,7 @@ LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | const fn const_val() -> usize { - | --------------------------------------- required by `Tt::const_val` + | --------- - required by this bound in `Tt::const_val` error[E0080]: evaluation of constant value failed --> $DIR/issue-54954.rs:13:15 From 61cfe92a992f8cd8b1af8e443c442be9559c3a19 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Tue, 24 Sep 2019 10:01:14 -0400 Subject: [PATCH 162/413] Add additional tests for type alias impl trait coherence --- src/test/ui/impl-trait/auto-trait.rs | 23 +++++++++++++++++++ src/test/ui/impl-trait/auto-trait.stderr | 12 ++++++++++ src/test/ui/impl-trait/negative-reasoning.rs | 22 ++++++++++++++++++ .../ui/impl-trait/negative-reasoning.stderr | 14 +++++++++++ 4 files changed, 71 insertions(+) create mode 100644 src/test/ui/impl-trait/auto-trait.rs create mode 100644 src/test/ui/impl-trait/auto-trait.stderr create mode 100644 src/test/ui/impl-trait/negative-reasoning.rs create mode 100644 src/test/ui/impl-trait/negative-reasoning.stderr diff --git a/src/test/ui/impl-trait/auto-trait.rs b/src/test/ui/impl-trait/auto-trait.rs new file mode 100644 index 0000000000000..c767578120883 --- /dev/null +++ b/src/test/ui/impl-trait/auto-trait.rs @@ -0,0 +1,23 @@ +// Tests that type alias impls traits do not leak auto-traits for +// the purposes of coherence checking +#![feature(type_alias_impl_trait)] + +trait OpaqueTrait { } +impl OpaqueTrait for T { } +type OpaqueType = impl OpaqueTrait; +fn mk_opaque() -> OpaqueType { () } + +#[derive(Debug)] +struct D(T); + +trait AnotherTrait { } +impl AnotherTrait for T { } + +// This is in error, because we cannot assume that `OpaqueType: !Send`. +// (We treat opaque types as "foreign types" that could grow more impls +// in the future.) +impl AnotherTrait for D { + //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` +} + +fn main() {} diff --git a/src/test/ui/impl-trait/auto-trait.stderr b/src/test/ui/impl-trait/auto-trait.stderr new file mode 100644 index 0000000000000..5e72ca7a47ba1 --- /dev/null +++ b/src/test/ui/impl-trait/auto-trait.stderr @@ -0,0 +1,12 @@ +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D`: + --> $DIR/auto-trait.rs:19:1 + | +LL | impl AnotherTrait for T { } + | -------------------------------- first implementation here +... +LL | impl AnotherTrait for D { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/src/test/ui/impl-trait/negative-reasoning.rs b/src/test/ui/impl-trait/negative-reasoning.rs new file mode 100644 index 0000000000000..4977f9bdbacd9 --- /dev/null +++ b/src/test/ui/impl-trait/negative-reasoning.rs @@ -0,0 +1,22 @@ +// Tests that we cannot assume that an opaque type does *not* implement some +// other trait +#![feature(type_alias_impl_trait)] + +trait OpaqueTrait { } +impl OpaqueTrait for T { } +type OpaqueType = impl OpaqueTrait; +fn mk_opaque() -> OpaqueType { () } + +#[derive(Debug)] +struct D(T); + +trait AnotherTrait { } +impl AnotherTrait for T { } + + +// This is in error, because we cannot assume that `OpaqueType: !Debug` +impl AnotherTrait for D { + //~^ ERROR conflicting implementations of trait `AnotherTrait` for type `D` +} + +fn main() {} diff --git a/src/test/ui/impl-trait/negative-reasoning.stderr b/src/test/ui/impl-trait/negative-reasoning.stderr new file mode 100644 index 0000000000000..526a664726ac2 --- /dev/null +++ b/src/test/ui/impl-trait/negative-reasoning.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D`: + --> $DIR/negative-reasoning.rs:18:1 + | +LL | impl AnotherTrait for T { } + | ------------------------------------------- first implementation here +... +LL | impl AnotherTrait for D { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D` + | + = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `OpaqueType` in future versions + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0119`. From 7b71abdb5490665e6e1f26486da0067904c1cd60 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 24 Sep 2019 22:42:45 +0200 Subject: [PATCH 163/413] Fix #64744 -- handle zero sub-pats case. --- src/librustc_typeck/check/pat.rs | 59 ++++++++++++++++++++++------ src/test/ui/error-codes/E0023.rs | 3 +- src/test/ui/error-codes/E0023.stderr | 15 ++++++- 3 files changed, 62 insertions(+), 15 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index d687a5084e231..2cd8507d753a6 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -676,7 +676,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } else { // Pattern has wrong number of fields. - self.e0023(pat.span, res, &subpats, &variant.fields, expected); + self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected); on_error(); return tcx.types.err; } @@ -687,22 +687,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, pat_span: Span, res: Res, + qpath: &hir::QPath, subpats: &'tcx [P], fields: &[ty::FieldDef], expected: Ty<'tcx> ) { let subpats_ending = pluralise!(subpats.len()); let fields_ending = pluralise!(fields.len()); - let missing_parenthesis = match expected.sty { - ty::Adt(_, substs) if fields.len() == 1 => { - let field_ty = fields[0].ty(self.tcx, substs); - match field_ty.sty { - ty::Tuple(_) => field_ty.tuple_fields().count() == subpats.len(), - _ => false, - } - } - _ => false, - }; let res_span = self.tcx.def_span(res.def_id()); let mut err = struct_span_err!( self.tcx.sess, @@ -723,11 +714,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )) .span_label(res_span, format!("{} defined here", res.descr())); + // Identify the case `Some(x, y)` where the expected type is e.g. `Option<(T, U)>`. + // More generally, the expected type wants a tuple variant with one field of an + // N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern + // with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`. + let missing_parenthesis = match expected.sty { + ty::Adt(_, substs) if fields.len() == 1 => { + let field_ty = fields[0].ty(self.tcx, substs); + match field_ty.sty { + ty::Tuple(_) => field_ty.tuple_fields().count() == subpats.len(), + _ => false, + } + } + _ => false, + }; if missing_parenthesis { + let (left, right) = match subpats { + // This is the zero case; we aim to get the "hi" part of the `QPath`'s + // span as the "lo" and then the "hi" part of the pattern's span as the "hi". + // This looks like: + // + // help: missing parenthesis + // | + // L | let A(()) = A(()); + // | ^ ^ + [] => { + let qpath_span = match qpath { + hir::QPath::Resolved(_, path) => path.span, + hir::QPath::TypeRelative(_, ps) => ps.ident.span, + }; + (qpath_span.shrink_to_hi(), pat_span) + }, + // Easy case. Just take the "lo" of the first sub-pattern and the "hi" of the + // last sub-pattern. In the case of `A(x)` the first and last may coincide. + // This looks like: + // + // help: missing parenthesis + // | + // L | let A((x, y)) = A((1, 2)); + // | ^ ^ + [first, ..] => (first.span.shrink_to_lo(), subpats.last().unwrap().span), + }; err.multipart_suggestion( "missing parenthesis", - vec![(subpats[0].span.shrink_to_lo(), "(".to_string()), - (subpats[subpats.len()-1].span.shrink_to_hi(), ")".to_string())], + vec![ + (left, "(".to_string()), + (right.shrink_to_hi(), ")".to_string()), + ], Applicability::MachineApplicable, ); } diff --git a/src/test/ui/error-codes/E0023.rs b/src/test/ui/error-codes/E0023.rs index dc421e060e86f..7ac22bb71092e 100644 --- a/src/test/ui/error-codes/E0023.rs +++ b/src/test/ui/error-codes/E0023.rs @@ -2,9 +2,9 @@ enum Fruit { Apple(String, String), Pear(u32), Orange((String, String)), + Banana(()), } - fn main() { let x = Fruit::Apple(String::new(), String::new()); match x { @@ -12,5 +12,6 @@ fn main() { Fruit::Apple(a, b, c) => {}, //~ ERROR E0023 Fruit::Pear(1, 2) => {}, //~ ERROR E0023 Fruit::Orange(a, b) => {}, //~ ERROR E0023 + Fruit::Banana() => {}, //~ ERROR E0023 } } diff --git a/src/test/ui/error-codes/E0023.stderr b/src/test/ui/error-codes/E0023.stderr index 8ae7d01ed5f7e..dbce6003a2bad 100644 --- a/src/test/ui/error-codes/E0023.stderr +++ b/src/test/ui/error-codes/E0023.stderr @@ -38,6 +38,19 @@ help: missing parenthesis LL | Fruit::Orange((a, b)) => {}, | ^ ^ -error: aborting due to 4 previous errors +error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 1 field + --> $DIR/E0023.rs:15:9 + | +LL | Banana(()), + | ---------- tuple variant defined here +... +LL | Fruit::Banana() => {}, + | ^^^^^^^^^^^^^^^ expected 1 field, found 0 +help: missing parenthesis + | +LL | Fruit::Banana(()) => {}, + | ^ ^ + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0023`. From 9249a7393c7fcc2813599fe90dfdb2ea784264d9 Mon Sep 17 00:00:00 2001 From: Georg Semmler Date: Tue, 24 Sep 2019 20:55:18 +0200 Subject: [PATCH 164/413] More path name fixes --- ...gn.rs => impl[t]-foreign[foreign[t]_local]-for-foreign.rs} | 0 ...s => impl[t]-foreign[fundamental[t]_local]-for-foreign.rs} | 0 ... impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr} | 4 ++-- ...s => impl[t]-foreign[local_fundamental[t]]-for-foreign.rs} | 0 4 files changed, 2 insertions(+), 2 deletions(-) rename src/test/ui/coherence/{impl[t]-foreign[foreign[t],local]-for-foreign.rs => impl[t]-foreign[foreign[t]_local]-for-foreign.rs} (100%) rename src/test/ui/coherence/{impl[t]-foreign[fundamental[t],local]-for-foreign.rs => impl[t]-foreign[fundamental[t]_local]-for-foreign.rs} (100%) rename src/test/ui/coherence/{impl[t]-foreign[fundamental[t],local]-for-foreign.stderr => impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr} (87%) rename src/test/ui/coherence/{impl[t]-foreign[local,fundamental[t]]-for-foreign.rs => impl[t]-foreign[local_fundamental[t]]-for-foreign.rs} (100%) diff --git a/src/test/ui/coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[foreign[t]_local]-for-foreign.rs similarity index 100% rename from src/test/ui/coherence/impl[t]-foreign[foreign[t],local]-for-foreign.rs rename to src/test/ui/coherence/impl[t]-foreign[foreign[t]_local]-for-foreign.rs diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs similarity index 100% rename from src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.rs rename to src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs diff --git a/src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.stderr b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr similarity index 87% rename from src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.stderr rename to src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr index da670bcfc3fc9..3d8561956ae7f 100644 --- a/src/test/ui/coherence/impl[t]-foreign[fundamental[t],local]-for-foreign.stderr +++ b/src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr @@ -1,5 +1,5 @@ error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[fundamental[t],local]-for-foreign.rs:12:1 + --> $DIR/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs:12:1 | LL | impl Remote2, Local> for u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type @@ -7,7 +7,7 @@ LL | impl Remote2, Local> for u32 { = note: only traits defined in the current crate can be implemented for a type parameter error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct`) - --> $DIR/impl[t]-foreign[fundamental[t],local]-for-foreign.rs:16:1 + --> $DIR/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs:16:1 | LL | impl<'a, T> Remote2<&'a T, Local> for u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `T` must be used as the type parameter for some local type diff --git a/src/test/ui/coherence/impl[t]-foreign[local,fundamental[t]]-for-foreign.rs b/src/test/ui/coherence/impl[t]-foreign[local_fundamental[t]]-for-foreign.rs similarity index 100% rename from src/test/ui/coherence/impl[t]-foreign[local,fundamental[t]]-for-foreign.rs rename to src/test/ui/coherence/impl[t]-foreign[local_fundamental[t]]-for-foreign.rs From 6d07874e883ae4334b42ef3ab04cc3f52ee711ee Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 24 Sep 2019 16:53:33 -0700 Subject: [PATCH 165/413] Don't emit explain with json short messages. --- src/libsyntax/json.rs | 7 +++++++ src/test/ui/json-short.stderr | 2 -- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index 5cdea3aabbe11..2423e1070fc3e 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -112,6 +112,13 @@ impl Emitter for JsonEmitter { panic!("failed to print notification: {:?}", e); } } + + fn should_show_explain(&self) -> bool { + match self.json_rendered { + HumanReadableErrorType::Short(_) => false, + _ => true, + } + } } // The following data types are provided just for serialisation. diff --git a/src/test/ui/json-short.stderr b/src/test/ui/json-short.stderr index 0a1fb567714fb..d9f68023ce76d 100644 --- a/src/test/ui/json-short.stderr +++ b/src/test/ui/json-short.stderr @@ -15,5 +15,3 @@ started: https://doc.rust-lang.org/book/ "} {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error "} -{"message":"For more information about this error, try `rustc --explain E0601`.","code":null,"level":"failure-note","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0601`. -"} From 9a020186f8d4411a9820c4e3378f86ea2ca72af5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 25 Sep 2019 10:14:47 +0300 Subject: [PATCH 166/413] remove unused parameters --- src/libsyntax/ext/mbe/macro_rules.rs | 8 -------- src/libsyntax/ext/mbe/quoted.rs | 24 +----------------------- 2 files changed, 1 insertion(+), 31 deletions(-) diff --git a/src/libsyntax/ext/mbe/macro_rules.rs b/src/libsyntax/ext/mbe/macro_rules.rs index 816baadb12fbb..87bb26c709e5e 100644 --- a/src/libsyntax/ext/mbe/macro_rules.rs +++ b/src/libsyntax/ext/mbe/macro_rules.rs @@ -371,10 +371,6 @@ pub fn compile_declarative_macro( tt.clone().into(), true, sess, - features, - &def.attrs, - edition, - def.id, ) .pop() .unwrap(); @@ -398,10 +394,6 @@ pub fn compile_declarative_macro( tt.clone().into(), false, sess, - features, - &def.attrs, - edition, - def.id, ) .pop() .unwrap(); diff --git a/src/libsyntax/ext/mbe/quoted.rs b/src/libsyntax/ext/mbe/quoted.rs index 3952e29a5f0d1..c881350fec3f8 100644 --- a/src/libsyntax/ext/mbe/quoted.rs +++ b/src/libsyntax/ext/mbe/quoted.rs @@ -1,15 +1,13 @@ use crate::ast; -use crate::ast::NodeId; use crate::ext::mbe::macro_parser; use crate::ext::mbe::{TokenTree, KleeneOp, KleeneToken, SequenceRepetition, Delimited}; -use crate::feature_gate::Features; use crate::parse::token::{self, Token}; use crate::parse::ParseSess; use crate::print::pprust; use crate::symbol::kw; use crate::tokenstream; -use syntax_pos::{edition::Edition, Span}; +use syntax_pos::Span; use rustc_data_structures::sync::Lrc; use std::iter::Peekable; @@ -39,10 +37,6 @@ pub(super) fn parse( input: tokenstream::TokenStream, expect_matchers: bool, sess: &ParseSess, - features: &Features, - attrs: &[ast::Attribute], - edition: Edition, - macro_node_id: NodeId, ) -> Vec { // Will contain the final collection of `self::TokenTree` let mut result = Vec::new(); @@ -58,10 +52,6 @@ pub(super) fn parse( &mut trees, expect_matchers, sess, - features, - attrs, - edition, - macro_node_id, ); match tree { TokenTree::MetaVar(start_sp, ident) if expect_matchers => { @@ -112,10 +102,6 @@ fn parse_tree( trees: &mut Peekable>, expect_matchers: bool, sess: &ParseSess, - features: &Features, - attrs: &[ast::Attribute], - edition: Edition, - macro_node_id: NodeId, ) -> TokenTree { // Depending on what `tree` is, we could be parsing different parts of a macro match tree { @@ -135,10 +121,6 @@ fn parse_tree( tts.into(), expect_matchers, sess, - features, - attrs, - edition, - macro_node_id, ); // Get the Kleene operator and optional separator let (separator, kleene) = parse_sep_and_kleene_op(trees, span.entire(), sess); @@ -192,10 +174,6 @@ fn parse_tree( tts.into(), expect_matchers, sess, - features, - attrs, - edition, - macro_node_id, ), }), ), From 538437e829fd1bdaaf5104f7750327cfdeed29bf Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 25 Sep 2019 10:17:59 +0300 Subject: [PATCH 167/413] move function closer to its usage --- src/libsyntax/ext/mbe/macro_parser.rs | 12 ------------ src/libsyntax/ext/mbe/macro_rules.rs | 15 ++++++++++++++- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/libsyntax/ext/mbe/macro_parser.rs b/src/libsyntax/ext/mbe/macro_parser.rs index b51384d3b15e1..8f49ba9572d77 100644 --- a/src/libsyntax/ext/mbe/macro_parser.rs +++ b/src/libsyntax/ext/mbe/macro_parser.rs @@ -413,18 +413,6 @@ fn nameize>( Success(ret_val) } -/// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For -/// other tokens, this is "unexpected token...". -crate fn parse_failure_msg(tok: &Token) -> String { - match tok.kind { - token::Eof => "unexpected end of macro invocation".to_string(), - _ => format!( - "no rules expected the token `{}`", - pprust::token_to_string(tok) - ), - } -} - /// Performs a token equality check, ignoring syntax context (that is, an unhygienic comparison) fn token_name_eq(t1: &Token, t2: &Token) -> bool { if let (Some((ident1, is_raw1)), Some((ident2, is_raw2))) = (t1.ident(), t2.ident()) { diff --git a/src/libsyntax/ext/mbe/macro_rules.rs b/src/libsyntax/ext/mbe/macro_rules.rs index 87bb26c709e5e..c24f6a666039f 100644 --- a/src/libsyntax/ext/mbe/macro_rules.rs +++ b/src/libsyntax/ext/mbe/macro_rules.rs @@ -6,7 +6,7 @@ use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind}; use crate::ext::expand::{AstFragment, AstFragmentKind}; use crate::ext::mbe; use crate::ext::mbe::macro_check; -use crate::ext::mbe::macro_parser::{parse, parse_failure_msg}; +use crate::ext::mbe::macro_parser::parse; use crate::ext::mbe::macro_parser::{Error, Failure, Success}; use crate::ext::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedParseResult}; use crate::ext::mbe::transcribe::transcribe; @@ -15,6 +15,7 @@ use crate::parse::parser::Parser; use crate::parse::token::TokenKind::*; use crate::parse::token::{self, NtTT, Token}; use crate::parse::{Directory, ParseSess}; +use crate::print::pprust; use crate::symbol::{kw, sym, Symbol}; use crate::tokenstream::{DelimSpan, TokenStream, TokenTree}; @@ -1176,3 +1177,15 @@ impl TokenTree { parse(cx.parse_sess(), tts, mtch, Some(directory), true) } } + +/// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For +/// other tokens, this is "unexpected token...". +fn parse_failure_msg(tok: &Token) -> String { + match tok.kind { + token::Eof => "unexpected end of macro invocation".to_string(), + _ => format!( + "no rules expected the token `{}`", + pprust::token_to_string(tok), + ), + } +} From f60a8734e088f3383512b0ffc12a9a909d2163b4 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 25 Sep 2019 10:41:43 +0300 Subject: [PATCH 168/413] remove unused peekable --- src/libsyntax/ext/mbe/quoted.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libsyntax/ext/mbe/quoted.rs b/src/libsyntax/ext/mbe/quoted.rs index c881350fec3f8..8cb85bdef762f 100644 --- a/src/libsyntax/ext/mbe/quoted.rs +++ b/src/libsyntax/ext/mbe/quoted.rs @@ -10,7 +10,6 @@ use crate::tokenstream; use syntax_pos::Span; use rustc_data_structures::sync::Lrc; -use std::iter::Peekable; /// Takes a `tokenstream::TokenStream` and returns a `Vec`. Specifically, this /// takes a generic `TokenStream`, such as is used in the rest of the compiler, and returns a @@ -43,7 +42,7 @@ pub(super) fn parse( // For each token tree in `input`, parse the token into a `self::TokenTree`, consuming // additional trees if need be. - let mut trees = input.trees().peekable(); + let mut trees = input.trees(); while let Some(tree) = trees.next() { // Given the parsed tree, if there is a metavar and we are expecting matchers, actually // parse out the matcher (i.e., in `$id:ident` this would parse the `:` and `ident`). @@ -99,7 +98,7 @@ pub(super) fn parse( /// unstable features or not. fn parse_tree( tree: tokenstream::TokenTree, - trees: &mut Peekable>, + trees: &mut impl Iterator, expect_matchers: bool, sess: &ParseSess, ) -> TokenTree { @@ -222,7 +221,7 @@ fn parse_kleene_op( /// operator and separator, then a tuple with `(separator, KleeneOp)` is returned. Otherwise, an /// error with the appropriate span is emitted to `sess` and a dummy value is returned. fn parse_sep_and_kleene_op( - input: &mut Peekable>, + input: &mut impl Iterator, span: Span, sess: &ParseSess, ) -> (Option, KleeneToken) { From 3a6e96e8bc8b7285c5a9b357d0e5e8dd9c191edf Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 25 Sep 2019 10:28:53 +0200 Subject: [PATCH 169/413] Allow simd_insert and simd_extract in const_fn --- src/librustc_mir/transform/qualify_consts.rs | 2 + .../const-eval/simd/insert_extract-fail.rs | 2 +- .../consts/const-eval/simd/insert_extract.rs | 2 +- .../const-eval/simd/insert_extract.stderr | 288 ------------------ 4 files changed, 4 insertions(+), 290 deletions(-) delete mode 100644 src/test/ui/consts/const-eval/simd/insert_extract.stderr diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 795721f3b3f28..8a6dcd1d2b476 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -557,6 +557,8 @@ impl Qualif for IsNotPromotable { | "saturating_add" | "saturating_sub" | "transmute" + | "simd_insert" + | "simd_extract" => return true, _ => {} diff --git a/src/test/ui/consts/const-eval/simd/insert_extract-fail.rs b/src/test/ui/consts/const-eval/simd/insert_extract-fail.rs index 20c839a81a04e..bbfae997e7241 100644 --- a/src/test/ui/consts/const-eval/simd/insert_extract-fail.rs +++ b/src/test/ui/consts/const-eval/simd/insert_extract-fail.rs @@ -1,4 +1,4 @@ -// compile-flags: -Zunleash-the-miri-inside-of-you +#![feature(const_fn)] #![feature(repr_simd)] #![feature(platform_intrinsics)] #![allow(non_camel_case_types)] diff --git a/src/test/ui/consts/const-eval/simd/insert_extract.rs b/src/test/ui/consts/const-eval/simd/insert_extract.rs index 136965bf68abf..d3462d802ea4e 100644 --- a/src/test/ui/consts/const-eval/simd/insert_extract.rs +++ b/src/test/ui/consts/const-eval/simd/insert_extract.rs @@ -1,5 +1,5 @@ // run-pass -// compile-flags: -Zunleash-the-miri-inside-of-you +#![feature(const_fn)] #![feature(repr_simd)] #![feature(platform_intrinsics)] #![allow(non_camel_case_types)] diff --git a/src/test/ui/consts/const-eval/simd/insert_extract.stderr b/src/test/ui/consts/const-eval/simd/insert_extract.stderr deleted file mode 100644 index 8975241403e74..0000000000000 --- a/src/test/ui/consts/const-eval/simd/insert_extract.stderr +++ /dev/null @@ -1,288 +0,0 @@ -warning: skipping const checks - --> $DIR/insert_extract.rs:22:9 - | -LL | assert_eq!(X0, 42); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:22:9 - | -LL | assert_eq!(X0, 42); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:22:9 - | -LL | assert_eq!(X0, 42); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:23:9 - | -LL | assert_eq!(Y0, 42); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:23:9 - | -LL | assert_eq!(Y0, 42); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:23:9 - | -LL | assert_eq!(Y0, 42); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:32:9 - | -LL | assert_eq!(X0, 13); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:32:9 - | -LL | assert_eq!(X0, 13); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:32:9 - | -LL | assert_eq!(X0, 13); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:33:9 - | -LL | assert_eq!(X1, 42); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:33:9 - | -LL | assert_eq!(X1, 42); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:33:9 - | -LL | assert_eq!(X1, 42); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:34:9 - | -LL | assert_eq!(Y0, 13); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:34:9 - | -LL | assert_eq!(Y0, 13); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:34:9 - | -LL | assert_eq!(Y0, 13); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:35:9 - | -LL | assert_eq!(Y1, 42); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:35:9 - | -LL | assert_eq!(Y1, 42); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:35:9 - | -LL | assert_eq!(Y1, 42); - | ^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:46:9 - | -LL | assert_eq!(X0, 13.); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:46:9 - | -LL | assert_eq!(X0, 13.); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:46:9 - | -LL | assert_eq!(X0, 13.); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:47:9 - | -LL | assert_eq!(X1, 42.); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:47:9 - | -LL | assert_eq!(X1, 42.); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:47:9 - | -LL | assert_eq!(X1, 42.); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:48:9 - | -LL | assert_eq!(X2, 15.); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:48:9 - | -LL | assert_eq!(X2, 15.); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:48:9 - | -LL | assert_eq!(X2, 15.); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:49:9 - | -LL | assert_eq!(Y0, 13.); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:49:9 - | -LL | assert_eq!(Y0, 13.); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:49:9 - | -LL | assert_eq!(Y0, 13.); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:50:9 - | -LL | assert_eq!(Y1, 42.); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:50:9 - | -LL | assert_eq!(Y1, 42.); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:50:9 - | -LL | assert_eq!(Y1, 42.); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:51:9 - | -LL | assert_eq!(Y2, 15.); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:51:9 - | -LL | assert_eq!(Y2, 15.); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - -warning: skipping const checks - --> $DIR/insert_extract.rs:51:9 - | -LL | assert_eq!(Y2, 15.); - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) - From 97ce904340f416b47c2b9790d550346bef5d7f7f Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 25 Sep 2019 10:33:12 +0200 Subject: [PATCH 170/413] Remove unreachable code --- src/librustc_mir/interpret/terminator.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index a324c58512406..8666c937ce4c2 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -249,11 +249,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { match instance.def { ty::InstanceDef::Intrinsic(..) => { - if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = caller_abi { - // ok - } else { - throw_unsup!(FunctionAbiMismatch(caller_abi, Abi::RustIntrinsic)) - } // The intrinsic itself cannot diverge, so if we got here without a return // place... (can happen e.g., for transmute returning `!`) let dest = match dest { From 02b3234a7766694616e3396c17e9ff08859a785d Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 25 Sep 2019 10:34:44 +0200 Subject: [PATCH 171/413] Tidy --- src/librustc_mir/interpret/intrinsics.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 630f5010b8598..fc1ec61c9629e 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -248,7 +248,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } else { throw_ub_format!( "Inserting `{}` with size `{}` to a vector element place of size `{}`", - scalar.layout.ty, scalar.layout.size.bytes(), vector[index].layout.size.bytes() + scalar.layout.ty, + scalar.layout.size.bytes(), vector[index].layout.size.bytes() ); } self.write_vector(vector, dest)?; From 5976674a717f61167a930df0c1fa1fe4106a439e Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 25 Sep 2019 12:54:23 +0200 Subject: [PATCH 172/413] Refactor --- src/librustc_mir/interpret/intrinsics.rs | 57 ++++++++++++++----- src/librustc_mir/interpret/operand.rs | 19 +++---- src/librustc_mir/interpret/place.rs | 34 ----------- .../const-eval/simd/insert_extract-fail.rs | 7 +++ .../ui/consts/const-eval/simd/read_fail.rs | 17 ++++++ 5 files changed, 76 insertions(+), 58 deletions(-) create mode 100644 src/test/ui/consts/const-eval/simd/read_fail.rs diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index fc1ec61c9629e..586611397e344 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -240,24 +240,55 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.copy_op_transmute(args[0], dest)?; } "simd_insert" => { - let mut vector = self.read_vector(args[0])?; - let index = self.read_scalar(args[1])?.to_u32()? as usize; + let index = self.read_scalar(args[1])?.to_u32()? as u64; let scalar = self.read_immediate(args[2])?; - if vector[index].layout.size == scalar.layout.size { - vector[index] = scalar; - } else { - throw_ub_format!( - "Inserting `{}` with size `{}` to a vector element place of size `{}`", - scalar.layout.ty, - scalar.layout.size.bytes(), vector[index].layout.size.bytes() - ); + let input = args[0]; + let (len, e_ty) = self.read_vector_ty(input); + assert!( + index < len, + "index `{}` must be in bounds of vector type `{}`: `[0, {})`", + index, e_ty, len + ); + assert_eq!( + args[0].layout, dest.layout, + "Return type `{}` must match vector type `{}`", + dest.layout.ty, input.layout.ty + ); + assert_eq!( + scalar.layout.ty, e_ty, + "Scalar type `{}` must match vector element type `{}`", + scalar.layout.ty, e_ty + ); + + for i in 0..len { + let place = self.place_field(dest, index)?; + if i == index { + self.write_immediate(*scalar, place)?; + } else { + self.write_immediate( + *self.read_immediate(self.operand_field(input, index)?)?, + place + )?; + }; } - self.write_vector(vector, dest)?; } "simd_extract" => { let index = self.read_scalar(args[1])?.to_u32()? as _; - let scalar = self.read_immediate(self.operand_field(args[0], index)?)?; - self.write_immediate(*scalar, dest)?; + let (len, e_ty) = self.read_vector_ty(args[0]); + assert!( + index < len, + "index `{}` must be in bounds of vector type `{}`: `[0, {})`", + index, e_ty, len + ); + assert_eq!( + e_ty, dest.layout.ty, + "Return type `{}` must match vector element type `{}`", + dest.layout.ty, e_ty + ); + self.write_immediate( + *self.read_immediate(self.operand_field(args[0], index)?)?, + dest + )?; } _ => return Ok(false), } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 184e2ee9516fc..c5771e4f34378 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -335,18 +335,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - /// Read vector from operand `op` - pub fn read_vector(&self, op: OpTy<'tcx, M::PointerTag>) - -> InterpResult<'tcx, Vec>> { - if let layout::Abi::Vector { count, .. } = op.layout.abi { - assert_ne!(count, 0); - let mut scalars = Vec::new(); - for index in 0..count { - scalars.push(self.read_immediate(self.operand_field(op, index as _)?)?); - } - Ok(scalars) + /// Read vector length and element type + pub fn read_vector_ty( + &self, op: OpTy<'tcx, M::PointerTag> + ) + -> (u64, &rustc::ty::TyS<'tcx>) { + if let layout::Abi::Vector { .. } = op.layout.abi { + (op.layout.ty.simd_size(*self.tcx) as _, op.layout.ty.simd_type(*self.tcx)) } else { - bug!("type is not a vector: {:?}, abi: {:?}", op.layout.ty, op.layout.abi); + bug!("Type `{}` is not a SIMD vector type", op.layout.ty) } } diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 9154e2666c598..c3660fb7a2e28 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -696,40 +696,6 @@ where Ok(()) } - /// Writes the `scalar` to the `index`-th element of the `vector`. - pub fn write_scalar_to_vector( - &mut self, - scalar: ImmTy<'tcx, M::PointerTag>, - vector: PlaceTy<'tcx, M::PointerTag>, - index: usize, - ) -> InterpResult<'tcx> { - let index = index as u64; - let place = self.place_field(vector, index)?; - self.write_immediate(*scalar, place)?; - Ok(()) - } - - /// Writes the `scalars` to the `vector`. - pub fn write_vector( - &mut self, - scalars: Vec>, - vector: PlaceTy<'tcx, M::PointerTag>, - ) -> InterpResult<'tcx> { - assert_ne!(scalars.len(), 0); - match vector.layout.ty.sty { - ty::Adt(def, ..) if def.repr.simd() => { - let tcx = &*self.tcx; - let count = vector.layout.ty.simd_size(*tcx); - assert_eq!(count, scalars.len()); - for index in 0..scalars.len() { - self.write_scalar_to_vector(scalars[index], vector, index)?; - } - } - _ => bug!("not a vector"), - } - Ok(()) - } - /// Write an `Immediate` to memory. #[inline(always)] pub fn write_immediate_to_mplace( diff --git a/src/test/ui/consts/const-eval/simd/insert_extract-fail.rs b/src/test/ui/consts/const-eval/simd/insert_extract-fail.rs index bbfae997e7241..1d1df8d25a406 100644 --- a/src/test/ui/consts/const-eval/simd/insert_extract-fail.rs +++ b/src/test/ui/consts/const-eval/simd/insert_extract-fail.rs @@ -7,6 +7,7 @@ extern "platform-intrinsic" { fn simd_insert(x: T, idx: u32, val: U) -> T; + fn simd_extract(x: T, idx: u32) -> U; } const fn foo(x: i8x1) -> i8 { @@ -14,7 +15,13 @@ const fn foo(x: i8x1) -> i8 { unsafe { simd_insert(x, 0_u32, 42_i16) }.0 //~ ERROR } +const fn bar(x: i8x1) -> i16 { + // the i8 is not a i16: + unsafe { simd_extract(x, 0_u32) } //~ ERROR +} + fn main() { const V: i8x1 = i8x1(13); const X: i8 = foo(V); + const Y: i16 = bar(V); } diff --git a/src/test/ui/consts/const-eval/simd/read_fail.rs b/src/test/ui/consts/const-eval/simd/read_fail.rs new file mode 100644 index 0000000000000..c5109c16e4c6d --- /dev/null +++ b/src/test/ui/consts/const-eval/simd/read_fail.rs @@ -0,0 +1,17 @@ +#![feature(const_fn)] +#![feature(platform_intrinsics)] +#![allow(non_camel_case_types)] + +extern "platform-intrinsic" { + fn simd_extract(x: T, idx: u32) -> U; +} + +const fn foo(x: i8) -> i8 { + // i8 is not a vector type: + unsafe { simd_extract(x, 0_u32) } //~ ERROR +} + +fn main() { + const V: i8 = 13; + const X: i8 = foo(V); +} From d8bf4f19a380cf38f71e24dd14e48f21512cb996 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 24 Sep 2019 14:01:19 +0200 Subject: [PATCH 173/413] Add long error explanation for E0533 --- src/librustc_typeck/error_codes.rs | 38 +++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index e11dcfafb8f8b..3a07171b12fb8 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -3610,6 +3610,43 @@ match r { ``` "##, +E0533: r##" +An item which isn't a unit struct, a variant, nor a constant has been used as a +match pattern. + +Erroneous code example: + +```compile_fail,E0533 +struct Tortoise; + +impl Tortoise { + fn turtle(&self) -> u32 { 0 } +} + +match 0u32 { + Tortoise::turtle => {} // Error! + _ => {} +} +if let Tortoise::turtle = 0u32 {} // Same error! +``` + +If you want to match against a value returned by a method, you need to bind the +value first: + +``` +struct Tortoise; + +impl Tortoise { + fn turtle(&self) -> u32 { 0 } +} + +match 0u32 { + x if x == Tortoise.turtle() => {} // Bound into `x` then we compare it! + _ => {} +} +``` +"##, + E0534: r##" The `inline` attribute was malformed. @@ -4935,7 +4972,6 @@ and the pin is required to keep it in the same place in memory. E0377, // the trait `CoerceUnsized` may only be implemented for a coercion // between structures with the same definition // E0558, // replaced with a generic attribute input check - E0533, // `{}` does not name a unit variant, unit struct or a constant // E0563, // cannot determine a type for this `impl Trait` removed in 6383de15 E0564, // only named lifetimes are allowed in `impl Trait`, // but `{}` was found in the type `{}` From e58e144e6634e3cbdfd6d415eb0ea24bc2a2bb87 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 24 Sep 2019 14:01:31 +0200 Subject: [PATCH 174/413] Update ui tests --- src/test/ui/methods/method-path-in-pattern.rs | 6 ++++++ .../ui/methods/method-path-in-pattern.stderr | 21 ++++++++++++++++++- .../ui/qualified/qualified-path-params.stderr | 3 ++- ...riant-form-through-Self-issue-58006.stderr | 1 + ...t-variant-form-through-alias-caught.stderr | 2 +- 5 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/test/ui/methods/method-path-in-pattern.rs b/src/test/ui/methods/method-path-in-pattern.rs index fb1cf7f71e70a..21a91f3f32b24 100644 --- a/src/test/ui/methods/method-path-in-pattern.rs +++ b/src/test/ui/methods/method-path-in-pattern.rs @@ -23,4 +23,10 @@ fn main() { ::trait_bar => {} //~^ ERROR expected unit struct/variant or constant, found method `::trait_bar` } + if let Foo::bar = 0u32 {} + //~^ ERROR expected unit struct/variant or constant, found method `::bar` + if let ::bar = 0u32 {} + //~^ ERROR expected unit struct/variant or constant, found method `::bar` + if let Foo::trait_bar = 0u32 {} + //~^ ERROR expected unit struct/variant or constant, found method `::trait_bar` } diff --git a/src/test/ui/methods/method-path-in-pattern.stderr b/src/test/ui/methods/method-path-in-pattern.stderr index 3f53ad768825b..257fff4c37dc0 100644 --- a/src/test/ui/methods/method-path-in-pattern.stderr +++ b/src/test/ui/methods/method-path-in-pattern.stderr @@ -16,5 +16,24 @@ error[E0533]: expected unit struct/variant or constant, found method `::tra LL | ::trait_bar => {} | ^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error[E0533]: expected unit struct/variant or constant, found method `::bar` + --> $DIR/method-path-in-pattern.rs:26:12 + | +LL | if let Foo::bar = 0u32 {} + | ^^^^^^^^ + +error[E0533]: expected unit struct/variant or constant, found method `::bar` + --> $DIR/method-path-in-pattern.rs:28:12 + | +LL | if let ::bar = 0u32 {} + | ^^^^^^^^^^ + +error[E0533]: expected unit struct/variant or constant, found method `::trait_bar` + --> $DIR/method-path-in-pattern.rs:30:12 + | +LL | if let Foo::trait_bar = 0u32 {} + | ^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors +For more information about this error, try `rustc --explain E0533`. diff --git a/src/test/ui/qualified/qualified-path-params.stderr b/src/test/ui/qualified/qualified-path-params.stderr index b8d3b744e837c..3e8fcdc7ca3e2 100644 --- a/src/test/ui/qualified/qualified-path-params.stderr +++ b/src/test/ui/qualified/qualified-path-params.stderr @@ -15,4 +15,5 @@ LL | 0 ..= ::A::f:: => {} error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0029`. +Some errors have detailed explanations: E0029, E0533. +For more information about an error, try `rustc --explain E0029`. diff --git a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr index 128a85e15634c..357b33de51b84 100644 --- a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr +++ b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-Self-issue-58006.stderr @@ -6,3 +6,4 @@ LL | Self::A => (), error: aborting due to previous error +For more information about this error, try `rustc --explain E0533`. diff --git a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr index c1ea816b7facf..c6528e417d8ae 100644 --- a/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr +++ b/src/test/ui/type-alias-enum-variants/incorrect-variant-form-through-alias-caught.stderr @@ -39,5 +39,5 @@ LL | let Alias::Unit() = panic!(); error: aborting due to 5 previous errors -Some errors have detailed explanations: E0164, E0618. +Some errors have detailed explanations: E0164, E0533, E0618. For more information about an error, try `rustc --explain E0164`. From 68d099a175334939047b99888b656661f32e13e3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 25 Sep 2019 13:23:53 +0200 Subject: [PATCH 175/413] Create new error code E0734 for stability attributes used outside of standard library --- src/librustc/error_codes.rs | 1 + src/librustc/middle/stability.rs | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index eee33846139e6..554e1a9ad828d 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -2247,4 +2247,5 @@ static X: u32 = 42; E0726, // non-explicit (not `'_`) elided lifetime in unsupported position E0727, // `async` generators are not yet supported E0728, // `await` must be in an `async` function or block + E0734, // stability attributes may not be used outside of the standard library } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index c06a0feb6a993..c45ae854e99eb 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -199,8 +199,12 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { let name = attr.name_or_empty(); if [sym::unstable, sym::stable, sym::rustc_deprecated].contains(&name) { attr::mark_used(attr); - self.tcx.sess.span_err(attr.span, "stability attributes may not be used \ - outside of the standard library"); + struct_span_err!( + self.tcx.sess, + attr.span, + E0734, + "stability attributes may not be used outside of the standard library", + ).emit(); } } From e74a268db511d4f124425c981300ebfaea0d64ee Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 25 Sep 2019 13:39:20 +0200 Subject: [PATCH 176/413] Test errors --- src/librustc_mir/interpret/intrinsics.rs | 25 +++++++---------- .../consts/const-eval/simd/extract-fail0.rs | 22 +++++++++++++++ .../const-eval/simd/extract-fail0.stderr | 15 +++++++++++ .../consts/const-eval/simd/extract-fail1.rs | 22 +++++++++++++++ .../const-eval/simd/extract-fail1.stderr | 15 +++++++++++ .../consts/const-eval/simd/extract-fail2.rs | 22 +++++++++++++++ .../const-eval/simd/extract-fail2.stderr | 13 +++++++++ .../ui/consts/const-eval/simd/insert-fail0.rs | 22 +++++++++++++++ .../const-eval/simd/insert-fail0.stderr | 15 +++++++++++ .../ui/consts/const-eval/simd/insert-fail1.rs | 22 +++++++++++++++ .../const-eval/simd/insert-fail1.stderr | 13 +++++++++ .../const-eval/simd/insert_extract-fail.rs | 27 ------------------- .../simd/insert_extract-fail.stderr | 16 ----------- .../ui/consts/const-eval/simd/read_fail.rs | 17 ------------ 14 files changed, 191 insertions(+), 75 deletions(-) create mode 100644 src/test/ui/consts/const-eval/simd/extract-fail0.rs create mode 100644 src/test/ui/consts/const-eval/simd/extract-fail0.stderr create mode 100644 src/test/ui/consts/const-eval/simd/extract-fail1.rs create mode 100644 src/test/ui/consts/const-eval/simd/extract-fail1.stderr create mode 100644 src/test/ui/consts/const-eval/simd/extract-fail2.rs create mode 100644 src/test/ui/consts/const-eval/simd/extract-fail2.stderr create mode 100644 src/test/ui/consts/const-eval/simd/insert-fail0.rs create mode 100644 src/test/ui/consts/const-eval/simd/insert-fail0.stderr create mode 100644 src/test/ui/consts/const-eval/simd/insert-fail1.rs create mode 100644 src/test/ui/consts/const-eval/simd/insert-fail1.stderr delete mode 100644 src/test/ui/consts/const-eval/simd/insert_extract-fail.rs delete mode 100644 src/test/ui/consts/const-eval/simd/insert_extract-fail.stderr delete mode 100644 src/test/ui/consts/const-eval/simd/read_fail.rs diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 586611397e344..5fc23b4a69ec5 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -241,16 +241,16 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } "simd_insert" => { let index = self.read_scalar(args[1])?.to_u32()? as u64; - let scalar = self.read_immediate(args[2])?; + let scalar = args[2]; let input = args[0]; let (len, e_ty) = self.read_vector_ty(input); assert!( index < len, - "index `{}` must be in bounds of vector type `{}`: `[0, {})`", + "Index `{}` must be in bounds of vector type `{}`: `[0, {})`", index, e_ty, len ); assert_eq!( - args[0].layout, dest.layout, + input.layout, dest.layout, "Return type `{}` must match vector type `{}`", dest.layout.ty, input.layout.ty ); @@ -261,15 +261,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ); for i in 0..len { - let place = self.place_field(dest, index)?; - if i == index { - self.write_immediate(*scalar, place)?; + let place = self.place_field(dest, i)?; + let value = if i == index { + scalar } else { - self.write_immediate( - *self.read_immediate(self.operand_field(input, index)?)?, - place - )?; + self.operand_field(input, i)? }; + self.copy_op(value, place)?; } } "simd_extract" => { @@ -277,7 +275,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let (len, e_ty) = self.read_vector_ty(args[0]); assert!( index < len, - "index `{}` must be in bounds of vector type `{}`: `[0, {})`", + "index `{}` is out-of-bounds of vector type `{}` with length `{}`", index, e_ty, len ); assert_eq!( @@ -285,10 +283,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { "Return type `{}` must match vector element type `{}`", dest.layout.ty, e_ty ); - self.write_immediate( - *self.read_immediate(self.operand_field(args[0], index)?)?, - dest - )?; + self.copy_op(self.operand_field(args[0], index)?, dest)?; } _ => return Ok(false), } diff --git a/src/test/ui/consts/const-eval/simd/extract-fail0.rs b/src/test/ui/consts/const-eval/simd/extract-fail0.rs new file mode 100644 index 0000000000000..d2c313ddd0cd4 --- /dev/null +++ b/src/test/ui/consts/const-eval/simd/extract-fail0.rs @@ -0,0 +1,22 @@ +// failure-status: 101 +// rustc-env:RUST_BACKTRACE=0 +#![feature(const_fn)] +#![feature(repr_simd)] +#![feature(platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] struct i8x1(i8); + +extern "platform-intrinsic" { + fn simd_extract(x: T, idx: u32) -> U; +} + +const X: i8x1 = i8x1(42); + +const fn extract_wrong_ret() -> i16 { + unsafe { simd_extract(X, 0_u32) } +} + +const A: i16 = extract_wrong_ret(); + +fn main() {} diff --git a/src/test/ui/consts/const-eval/simd/extract-fail0.stderr b/src/test/ui/consts/const-eval/simd/extract-fail0.stderr new file mode 100644 index 0000000000000..51518481941df --- /dev/null +++ b/src/test/ui/consts/const-eval/simd/extract-fail0.stderr @@ -0,0 +1,15 @@ +thread 'rustc' panicked at 'assertion failed: `(left == right)` + left: `i8`, + right: `i16`: Return type `i16` must match vector element type `i8`', src/librustc_mir/interpret/intrinsics.rs:281:17 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. + +error: internal compiler error: unexpected panic + +note: the compiler unexpectedly panicked. this is a bug. + +note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports + +note: rustc 1.39.0-dev running on x86_64-apple-darwin + +note: compiler flags: -Z threads=1 -Z ui-testing -Z unstable-options -C prefer-dynamic -C rpath -C debuginfo=0 + diff --git a/src/test/ui/consts/const-eval/simd/extract-fail1.rs b/src/test/ui/consts/const-eval/simd/extract-fail1.rs new file mode 100644 index 0000000000000..ddff608181e93 --- /dev/null +++ b/src/test/ui/consts/const-eval/simd/extract-fail1.rs @@ -0,0 +1,22 @@ +// failure-status: 101 +// rustc-env:RUST_BACKTRACE=0 +#![feature(const_fn)] +#![feature(repr_simd)] +#![feature(platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] struct i8x1(i8); + +extern "platform-intrinsic" { + fn simd_extract(x: T, idx: u32) -> U; +} + +const X: i8x1 = i8x1(42); + +const fn extract_wrong_vec() -> i8 { + unsafe { simd_extract(42_i8, 0_u32) } +} + +const B: i8 = extract_wrong_vec(); + +fn main() {} diff --git a/src/test/ui/consts/const-eval/simd/extract-fail1.stderr b/src/test/ui/consts/const-eval/simd/extract-fail1.stderr new file mode 100644 index 0000000000000..a00d98bf7fd9b --- /dev/null +++ b/src/test/ui/consts/const-eval/simd/extract-fail1.stderr @@ -0,0 +1,15 @@ +error: internal compiler error: src/librustc_mir/interpret/operand.rs:346: Type `i8` is not a SIMD vector type + +thread 'rustc' panicked at 'Box', src/librustc_errors/lib.rs:643:9 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. + +note: the compiler unexpectedly panicked. this is a bug. + +note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports + +note: rustc 1.39.0-dev running on x86_64-apple-darwin + +note: compiler flags: -Z threads=1 -Z ui-testing -Z unstable-options -C prefer-dynamic -C rpath -C debuginfo=0 + +error: aborting due to previous error + diff --git a/src/test/ui/consts/const-eval/simd/extract-fail2.rs b/src/test/ui/consts/const-eval/simd/extract-fail2.rs new file mode 100644 index 0000000000000..e2eb449f977ce --- /dev/null +++ b/src/test/ui/consts/const-eval/simd/extract-fail2.rs @@ -0,0 +1,22 @@ +// failure-status: 101 +// rustc-env:RUST_BACKTRACE=0 +#![feature(const_fn)] +#![feature(repr_simd)] +#![feature(platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] struct i8x1(i8); + +extern "platform-intrinsic" { + fn simd_extract(x: T, idx: u32) -> U; +} + +const X: i8x1 = i8x1(42); + +const fn extract_wrong_idx() -> i8 { + unsafe { simd_extract(X, 1_u32) } +} + +const C: i8 = extract_wrong_idx(); + +fn main() {} diff --git a/src/test/ui/consts/const-eval/simd/extract-fail2.stderr b/src/test/ui/consts/const-eval/simd/extract-fail2.stderr new file mode 100644 index 0000000000000..5d74e115ef87f --- /dev/null +++ b/src/test/ui/consts/const-eval/simd/extract-fail2.stderr @@ -0,0 +1,13 @@ +thread 'rustc' panicked at 'index `1` is out-of-bounds of vector type `i8` with length `1`', src/librustc_mir/interpret/intrinsics.rs:276:17 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. + +error: internal compiler error: unexpected panic + +note: the compiler unexpectedly panicked. this is a bug. + +note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports + +note: rustc 1.39.0-dev running on x86_64-apple-darwin + +note: compiler flags: -Z threads=1 -Z ui-testing -Z unstable-options -C prefer-dynamic -C rpath -C debuginfo=0 + diff --git a/src/test/ui/consts/const-eval/simd/insert-fail0.rs b/src/test/ui/consts/const-eval/simd/insert-fail0.rs new file mode 100644 index 0000000000000..dca58fb2555a8 --- /dev/null +++ b/src/test/ui/consts/const-eval/simd/insert-fail0.rs @@ -0,0 +1,22 @@ +// failure-status: 101 +// rustc-env:RUST_BACKTRACE=0 +#![feature(const_fn)] +#![feature(repr_simd)] +#![feature(platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] struct i8x1(i8); + +extern "platform-intrinsic" { + fn simd_insert(x: T, idx: u32, val: U) -> T; +} + +const X: i8x1 = i8x1(42); + +const fn insert_wrong_scalar() -> i8x1 { + unsafe { simd_insert(X, 0_u32, 42_i16) } +} + +const D: i8x1 = insert_wrong_scalar(); + +fn main() {} diff --git a/src/test/ui/consts/const-eval/simd/insert-fail0.stderr b/src/test/ui/consts/const-eval/simd/insert-fail0.stderr new file mode 100644 index 0000000000000..1ea31ec8deb6a --- /dev/null +++ b/src/test/ui/consts/const-eval/simd/insert-fail0.stderr @@ -0,0 +1,15 @@ +thread 'rustc' panicked at 'assertion failed: `(left == right)` + left: `i16`, + right: `i8`: Scalar type `i16` must match vector element type `i8`', src/librustc_mir/interpret/intrinsics.rs:257:17 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. + +error: internal compiler error: unexpected panic + +note: the compiler unexpectedly panicked. this is a bug. + +note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports + +note: rustc 1.39.0-dev running on x86_64-apple-darwin + +note: compiler flags: -Z threads=1 -Z ui-testing -Z unstable-options -C prefer-dynamic -C rpath -C debuginfo=0 + diff --git a/src/test/ui/consts/const-eval/simd/insert-fail1.rs b/src/test/ui/consts/const-eval/simd/insert-fail1.rs new file mode 100644 index 0000000000000..2a3d79b76c306 --- /dev/null +++ b/src/test/ui/consts/const-eval/simd/insert-fail1.rs @@ -0,0 +1,22 @@ +// failure-status: 101 +// rustc-env:RUST_BACKTRACE=0 +#![feature(const_fn)] +#![feature(repr_simd)] +#![feature(platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] struct i8x1(i8); + +extern "platform-intrinsic" { + fn simd_insert(x: T, idx: u32, val: U) -> T; +} + +const X: i8x1 = i8x1(42); + +const fn insert_wrong_idx() -> i8x1 { + unsafe { simd_insert(X, 1_u32, 42_i8) } +} + +const E: i8x1 = insert_wrong_idx(); + +fn main() {} diff --git a/src/test/ui/consts/const-eval/simd/insert-fail1.stderr b/src/test/ui/consts/const-eval/simd/insert-fail1.stderr new file mode 100644 index 0000000000000..38d3782263010 --- /dev/null +++ b/src/test/ui/consts/const-eval/simd/insert-fail1.stderr @@ -0,0 +1,13 @@ +thread 'rustc' panicked at 'Index `1` must be in bounds of vector type `i8`: `[0, 1)`', src/librustc_mir/interpret/intrinsics.rs:247:17 +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. + +error: internal compiler error: unexpected panic + +note: the compiler unexpectedly panicked. this is a bug. + +note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports + +note: rustc 1.39.0-dev running on x86_64-apple-darwin + +note: compiler flags: -Z threads=1 -Z ui-testing -Z unstable-options -C prefer-dynamic -C rpath -C debuginfo=0 + diff --git a/src/test/ui/consts/const-eval/simd/insert_extract-fail.rs b/src/test/ui/consts/const-eval/simd/insert_extract-fail.rs deleted file mode 100644 index 1d1df8d25a406..0000000000000 --- a/src/test/ui/consts/const-eval/simd/insert_extract-fail.rs +++ /dev/null @@ -1,27 +0,0 @@ -#![feature(const_fn)] -#![feature(repr_simd)] -#![feature(platform_intrinsics)] -#![allow(non_camel_case_types)] - -#[repr(simd)] struct i8x1(i8); - -extern "platform-intrinsic" { - fn simd_insert(x: T, idx: u32, val: U) -> T; - fn simd_extract(x: T, idx: u32) -> U; -} - -const fn foo(x: i8x1) -> i8 { - // 42 is a i16 that does not fit in a i8 - unsafe { simd_insert(x, 0_u32, 42_i16) }.0 //~ ERROR -} - -const fn bar(x: i8x1) -> i16 { - // the i8 is not a i16: - unsafe { simd_extract(x, 0_u32) } //~ ERROR -} - -fn main() { - const V: i8x1 = i8x1(13); - const X: i8 = foo(V); - const Y: i16 = bar(V); -} diff --git a/src/test/ui/consts/const-eval/simd/insert_extract-fail.stderr b/src/test/ui/consts/const-eval/simd/insert_extract-fail.stderr deleted file mode 100644 index cf4e6887f16d5..0000000000000 --- a/src/test/ui/consts/const-eval/simd/insert_extract-fail.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: any use of this value will cause an error - --> $DIR/insert_extract-fail.rs:14:14 - | -LL | unsafe { simd_insert(x, 0_u32, 42_i16) }.0 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | Inserting `i16` with size `2` to a vector element place of size `1` - | inside call to `foo` at $DIR/insert_extract-fail.rs:19:19 -... -LL | const X: i8 = foo(V); - | --------------------- - | - = note: `#[deny(const_err)]` on by default - -error: aborting due to previous error - diff --git a/src/test/ui/consts/const-eval/simd/read_fail.rs b/src/test/ui/consts/const-eval/simd/read_fail.rs deleted file mode 100644 index c5109c16e4c6d..0000000000000 --- a/src/test/ui/consts/const-eval/simd/read_fail.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(const_fn)] -#![feature(platform_intrinsics)] -#![allow(non_camel_case_types)] - -extern "platform-intrinsic" { - fn simd_extract(x: T, idx: u32) -> U; -} - -const fn foo(x: i8) -> i8 { - // i8 is not a vector type: - unsafe { simd_extract(x, 0_u32) } //~ ERROR -} - -fn main() { - const V: i8 = 13; - const X: i8 = foo(V); -} From e1cf0a1d677a6f583baf96b14dccf61ec5e4cfeb Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 25 Sep 2019 13:39:28 +0200 Subject: [PATCH 177/413] Format --- src/librustc_mir/interpret/operand.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index c5771e4f34378..afaf9d7ed9d67 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -338,8 +338,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// Read vector length and element type pub fn read_vector_ty( &self, op: OpTy<'tcx, M::PointerTag> - ) - -> (u64, &rustc::ty::TyS<'tcx>) { + ) -> (u64, &rustc::ty::TyS<'tcx>) { if let layout::Abi::Vector { .. } = op.layout.abi { (op.layout.ty.simd_size(*self.tcx) as _, op.layout.ty.simd_type(*self.tcx)) } else { From 02bfbf96c7c241146957a75128ad63276fa0b671 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 25 Sep 2019 14:05:39 +0200 Subject: [PATCH 178/413] Clean tests --- src/test/ui/consts/const-eval/simd/extract-fail0.rs | 4 ++++ src/test/ui/consts/const-eval/simd/extract-fail0.stderr | 4 ++-- src/test/ui/consts/const-eval/simd/extract-fail1.rs | 4 ++++ src/test/ui/consts/const-eval/simd/extract-fail1.stderr | 6 +++--- src/test/ui/consts/const-eval/simd/extract-fail2.rs | 4 ++++ src/test/ui/consts/const-eval/simd/extract-fail2.stderr | 4 ++-- src/test/ui/consts/const-eval/simd/insert-fail0.rs | 4 ++++ src/test/ui/consts/const-eval/simd/insert-fail0.stderr | 4 ++-- src/test/ui/consts/const-eval/simd/insert-fail1.rs | 4 ++++ src/test/ui/consts/const-eval/simd/insert-fail1.stderr | 4 ++-- 10 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/test/ui/consts/const-eval/simd/extract-fail0.rs b/src/test/ui/consts/const-eval/simd/extract-fail0.rs index d2c313ddd0cd4..4a046e424c528 100644 --- a/src/test/ui/consts/const-eval/simd/extract-fail0.rs +++ b/src/test/ui/consts/const-eval/simd/extract-fail0.rs @@ -1,5 +1,9 @@ // failure-status: 101 // rustc-env:RUST_BACKTRACE=0 +// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" +// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" +// normalize-stderr-test "interpret/intern.rs:[0-9]*:[0-9]*" -> "interpret/intern.rs:LL:CC" + #![feature(const_fn)] #![feature(repr_simd)] #![feature(platform_intrinsics)] diff --git a/src/test/ui/consts/const-eval/simd/extract-fail0.stderr b/src/test/ui/consts/const-eval/simd/extract-fail0.stderr index 51518481941df..be2c2607002e0 100644 --- a/src/test/ui/consts/const-eval/simd/extract-fail0.stderr +++ b/src/test/ui/consts/const-eval/simd/extract-fail0.stderr @@ -9,7 +9,7 @@ note: the compiler unexpectedly panicked. this is a bug. note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports -note: rustc 1.39.0-dev running on x86_64-apple-darwin +note: rustc VERSION running on TARGET -note: compiler flags: -Z threads=1 -Z ui-testing -Z unstable-options -C prefer-dynamic -C rpath -C debuginfo=0 +note: compiler flags: FLAGS diff --git a/src/test/ui/consts/const-eval/simd/extract-fail1.rs b/src/test/ui/consts/const-eval/simd/extract-fail1.rs index ddff608181e93..ec281a19b17d0 100644 --- a/src/test/ui/consts/const-eval/simd/extract-fail1.rs +++ b/src/test/ui/consts/const-eval/simd/extract-fail1.rs @@ -1,5 +1,9 @@ // failure-status: 101 // rustc-env:RUST_BACKTRACE=0 +// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" +// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" +// normalize-stderr-test "interpret/intern.rs:[0-9]*:[0-9]*" -> "interpret/intern.rs:LL:CC" + #![feature(const_fn)] #![feature(repr_simd)] #![feature(platform_intrinsics)] diff --git a/src/test/ui/consts/const-eval/simd/extract-fail1.stderr b/src/test/ui/consts/const-eval/simd/extract-fail1.stderr index a00d98bf7fd9b..8c53ee874c466 100644 --- a/src/test/ui/consts/const-eval/simd/extract-fail1.stderr +++ b/src/test/ui/consts/const-eval/simd/extract-fail1.stderr @@ -1,4 +1,4 @@ -error: internal compiler error: src/librustc_mir/interpret/operand.rs:346: Type `i8` is not a SIMD vector type +error: internal compiler error: src/librustc_mir/interpret/operand.rs:345: Type `i8` is not a SIMD vector type thread 'rustc' panicked at 'Box', src/librustc_errors/lib.rs:643:9 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. @@ -7,9 +7,9 @@ note: the compiler unexpectedly panicked. this is a bug. note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports -note: rustc 1.39.0-dev running on x86_64-apple-darwin +note: rustc VERSION running on TARGET -note: compiler flags: -Z threads=1 -Z ui-testing -Z unstable-options -C prefer-dynamic -C rpath -C debuginfo=0 +note: compiler flags: FLAGS error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/simd/extract-fail2.rs b/src/test/ui/consts/const-eval/simd/extract-fail2.rs index e2eb449f977ce..d1970877574f8 100644 --- a/src/test/ui/consts/const-eval/simd/extract-fail2.rs +++ b/src/test/ui/consts/const-eval/simd/extract-fail2.rs @@ -1,5 +1,9 @@ // failure-status: 101 // rustc-env:RUST_BACKTRACE=0 +// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" +// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" +// normalize-stderr-test "interpret/intern.rs:[0-9]*:[0-9]*" -> "interpret/intern.rs:LL:CC" + #![feature(const_fn)] #![feature(repr_simd)] #![feature(platform_intrinsics)] diff --git a/src/test/ui/consts/const-eval/simd/extract-fail2.stderr b/src/test/ui/consts/const-eval/simd/extract-fail2.stderr index 5d74e115ef87f..1885c930e9a2b 100644 --- a/src/test/ui/consts/const-eval/simd/extract-fail2.stderr +++ b/src/test/ui/consts/const-eval/simd/extract-fail2.stderr @@ -7,7 +7,7 @@ note: the compiler unexpectedly panicked. this is a bug. note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports -note: rustc 1.39.0-dev running on x86_64-apple-darwin +note: rustc VERSION running on TARGET -note: compiler flags: -Z threads=1 -Z ui-testing -Z unstable-options -C prefer-dynamic -C rpath -C debuginfo=0 +note: compiler flags: FLAGS diff --git a/src/test/ui/consts/const-eval/simd/insert-fail0.rs b/src/test/ui/consts/const-eval/simd/insert-fail0.rs index dca58fb2555a8..2ee0fdfc1ec6b 100644 --- a/src/test/ui/consts/const-eval/simd/insert-fail0.rs +++ b/src/test/ui/consts/const-eval/simd/insert-fail0.rs @@ -1,5 +1,9 @@ // failure-status: 101 // rustc-env:RUST_BACKTRACE=0 +// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" +// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" +// normalize-stderr-test "interpret/intern.rs:[0-9]*:[0-9]*" -> "interpret/intern.rs:LL:CC" + #![feature(const_fn)] #![feature(repr_simd)] #![feature(platform_intrinsics)] diff --git a/src/test/ui/consts/const-eval/simd/insert-fail0.stderr b/src/test/ui/consts/const-eval/simd/insert-fail0.stderr index 1ea31ec8deb6a..1d0173ed33272 100644 --- a/src/test/ui/consts/const-eval/simd/insert-fail0.stderr +++ b/src/test/ui/consts/const-eval/simd/insert-fail0.stderr @@ -9,7 +9,7 @@ note: the compiler unexpectedly panicked. this is a bug. note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports -note: rustc 1.39.0-dev running on x86_64-apple-darwin +note: rustc VERSION running on TARGET -note: compiler flags: -Z threads=1 -Z ui-testing -Z unstable-options -C prefer-dynamic -C rpath -C debuginfo=0 +note: compiler flags: FLAGS diff --git a/src/test/ui/consts/const-eval/simd/insert-fail1.rs b/src/test/ui/consts/const-eval/simd/insert-fail1.rs index 2a3d79b76c306..146b8ce6a130a 100644 --- a/src/test/ui/consts/const-eval/simd/insert-fail1.rs +++ b/src/test/ui/consts/const-eval/simd/insert-fail1.rs @@ -1,5 +1,9 @@ // failure-status: 101 // rustc-env:RUST_BACKTRACE=0 +// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" +// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" +// normalize-stderr-test "interpret/intern.rs:[0-9]*:[0-9]*" -> "interpret/intern.rs:LL:CC" + #![feature(const_fn)] #![feature(repr_simd)] #![feature(platform_intrinsics)] diff --git a/src/test/ui/consts/const-eval/simd/insert-fail1.stderr b/src/test/ui/consts/const-eval/simd/insert-fail1.stderr index 38d3782263010..6223f308c2f35 100644 --- a/src/test/ui/consts/const-eval/simd/insert-fail1.stderr +++ b/src/test/ui/consts/const-eval/simd/insert-fail1.stderr @@ -7,7 +7,7 @@ note: the compiler unexpectedly panicked. this is a bug. note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports -note: rustc 1.39.0-dev running on x86_64-apple-darwin +note: rustc VERSION running on TARGET -note: compiler flags: -Z threads=1 -Z ui-testing -Z unstable-options -C prefer-dynamic -C rpath -C debuginfo=0 +note: compiler flags: FLAGS From 1a4e4d937e9a5ffb907063fc0837799a87cd1508 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 25 Sep 2019 08:20:32 -0400 Subject: [PATCH 179/413] Switch version to 1.40 --- src/bootstrap/channel.rs | 2 +- src/stage0.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index caa4843da4d36..ef1b6e217a24f 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -13,7 +13,7 @@ use build_helper::output; use crate::Build; // The version number -pub const CFG_RELEASE_NUM: &str = "1.39.0"; +pub const CFG_RELEASE_NUM: &str = "1.40.0"; pub struct GitInfo { inner: Option, diff --git a/src/stage0.txt b/src/stage0.txt index 1a9e64a1862c9..9509d3e99612f 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,7 +12,7 @@ # source tarball for a stable release you'll likely see `1.x.0` for rustc and # `0.x.0` for Cargo where they were released on `date`. -date: 2019-08-13 +date: 2019-09-25 rustc: beta cargo: beta From 5ecb7eb161e75ab33ca015e7f717424f32af3d59 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 25 Sep 2019 14:32:57 +0200 Subject: [PATCH 180/413] Remove fail tests --- .../consts/const-eval/simd/extract-fail0.rs | 26 ------------------- .../const-eval/simd/extract-fail0.stderr | 15 ----------- .../consts/const-eval/simd/extract-fail1.rs | 26 ------------------- .../const-eval/simd/extract-fail1.stderr | 15 ----------- .../consts/const-eval/simd/extract-fail2.rs | 26 ------------------- .../const-eval/simd/extract-fail2.stderr | 13 ---------- .../ui/consts/const-eval/simd/insert-fail0.rs | 26 ------------------- .../const-eval/simd/insert-fail0.stderr | 15 ----------- .../ui/consts/const-eval/simd/insert-fail1.rs | 26 ------------------- .../const-eval/simd/insert-fail1.stderr | 13 ---------- 10 files changed, 201 deletions(-) delete mode 100644 src/test/ui/consts/const-eval/simd/extract-fail0.rs delete mode 100644 src/test/ui/consts/const-eval/simd/extract-fail0.stderr delete mode 100644 src/test/ui/consts/const-eval/simd/extract-fail1.rs delete mode 100644 src/test/ui/consts/const-eval/simd/extract-fail1.stderr delete mode 100644 src/test/ui/consts/const-eval/simd/extract-fail2.rs delete mode 100644 src/test/ui/consts/const-eval/simd/extract-fail2.stderr delete mode 100644 src/test/ui/consts/const-eval/simd/insert-fail0.rs delete mode 100644 src/test/ui/consts/const-eval/simd/insert-fail0.stderr delete mode 100644 src/test/ui/consts/const-eval/simd/insert-fail1.rs delete mode 100644 src/test/ui/consts/const-eval/simd/insert-fail1.stderr diff --git a/src/test/ui/consts/const-eval/simd/extract-fail0.rs b/src/test/ui/consts/const-eval/simd/extract-fail0.rs deleted file mode 100644 index 4a046e424c528..0000000000000 --- a/src/test/ui/consts/const-eval/simd/extract-fail0.rs +++ /dev/null @@ -1,26 +0,0 @@ -// failure-status: 101 -// rustc-env:RUST_BACKTRACE=0 -// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" -// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" -// normalize-stderr-test "interpret/intern.rs:[0-9]*:[0-9]*" -> "interpret/intern.rs:LL:CC" - -#![feature(const_fn)] -#![feature(repr_simd)] -#![feature(platform_intrinsics)] -#![allow(non_camel_case_types)] - -#[repr(simd)] struct i8x1(i8); - -extern "platform-intrinsic" { - fn simd_extract(x: T, idx: u32) -> U; -} - -const X: i8x1 = i8x1(42); - -const fn extract_wrong_ret() -> i16 { - unsafe { simd_extract(X, 0_u32) } -} - -const A: i16 = extract_wrong_ret(); - -fn main() {} diff --git a/src/test/ui/consts/const-eval/simd/extract-fail0.stderr b/src/test/ui/consts/const-eval/simd/extract-fail0.stderr deleted file mode 100644 index be2c2607002e0..0000000000000 --- a/src/test/ui/consts/const-eval/simd/extract-fail0.stderr +++ /dev/null @@ -1,15 +0,0 @@ -thread 'rustc' panicked at 'assertion failed: `(left == right)` - left: `i8`, - right: `i16`: Return type `i16` must match vector element type `i8`', src/librustc_mir/interpret/intrinsics.rs:281:17 -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. - -error: internal compiler error: unexpected panic - -note: the compiler unexpectedly panicked. this is a bug. - -note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports - -note: rustc VERSION running on TARGET - -note: compiler flags: FLAGS - diff --git a/src/test/ui/consts/const-eval/simd/extract-fail1.rs b/src/test/ui/consts/const-eval/simd/extract-fail1.rs deleted file mode 100644 index ec281a19b17d0..0000000000000 --- a/src/test/ui/consts/const-eval/simd/extract-fail1.rs +++ /dev/null @@ -1,26 +0,0 @@ -// failure-status: 101 -// rustc-env:RUST_BACKTRACE=0 -// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" -// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" -// normalize-stderr-test "interpret/intern.rs:[0-9]*:[0-9]*" -> "interpret/intern.rs:LL:CC" - -#![feature(const_fn)] -#![feature(repr_simd)] -#![feature(platform_intrinsics)] -#![allow(non_camel_case_types)] - -#[repr(simd)] struct i8x1(i8); - -extern "platform-intrinsic" { - fn simd_extract(x: T, idx: u32) -> U; -} - -const X: i8x1 = i8x1(42); - -const fn extract_wrong_vec() -> i8 { - unsafe { simd_extract(42_i8, 0_u32) } -} - -const B: i8 = extract_wrong_vec(); - -fn main() {} diff --git a/src/test/ui/consts/const-eval/simd/extract-fail1.stderr b/src/test/ui/consts/const-eval/simd/extract-fail1.stderr deleted file mode 100644 index 8c53ee874c466..0000000000000 --- a/src/test/ui/consts/const-eval/simd/extract-fail1.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: internal compiler error: src/librustc_mir/interpret/operand.rs:345: Type `i8` is not a SIMD vector type - -thread 'rustc' panicked at 'Box', src/librustc_errors/lib.rs:643:9 -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. - -note: the compiler unexpectedly panicked. this is a bug. - -note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports - -note: rustc VERSION running on TARGET - -note: compiler flags: FLAGS - -error: aborting due to previous error - diff --git a/src/test/ui/consts/const-eval/simd/extract-fail2.rs b/src/test/ui/consts/const-eval/simd/extract-fail2.rs deleted file mode 100644 index d1970877574f8..0000000000000 --- a/src/test/ui/consts/const-eval/simd/extract-fail2.rs +++ /dev/null @@ -1,26 +0,0 @@ -// failure-status: 101 -// rustc-env:RUST_BACKTRACE=0 -// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" -// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" -// normalize-stderr-test "interpret/intern.rs:[0-9]*:[0-9]*" -> "interpret/intern.rs:LL:CC" - -#![feature(const_fn)] -#![feature(repr_simd)] -#![feature(platform_intrinsics)] -#![allow(non_camel_case_types)] - -#[repr(simd)] struct i8x1(i8); - -extern "platform-intrinsic" { - fn simd_extract(x: T, idx: u32) -> U; -} - -const X: i8x1 = i8x1(42); - -const fn extract_wrong_idx() -> i8 { - unsafe { simd_extract(X, 1_u32) } -} - -const C: i8 = extract_wrong_idx(); - -fn main() {} diff --git a/src/test/ui/consts/const-eval/simd/extract-fail2.stderr b/src/test/ui/consts/const-eval/simd/extract-fail2.stderr deleted file mode 100644 index 1885c930e9a2b..0000000000000 --- a/src/test/ui/consts/const-eval/simd/extract-fail2.stderr +++ /dev/null @@ -1,13 +0,0 @@ -thread 'rustc' panicked at 'index `1` is out-of-bounds of vector type `i8` with length `1`', src/librustc_mir/interpret/intrinsics.rs:276:17 -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. - -error: internal compiler error: unexpected panic - -note: the compiler unexpectedly panicked. this is a bug. - -note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports - -note: rustc VERSION running on TARGET - -note: compiler flags: FLAGS - diff --git a/src/test/ui/consts/const-eval/simd/insert-fail0.rs b/src/test/ui/consts/const-eval/simd/insert-fail0.rs deleted file mode 100644 index 2ee0fdfc1ec6b..0000000000000 --- a/src/test/ui/consts/const-eval/simd/insert-fail0.rs +++ /dev/null @@ -1,26 +0,0 @@ -// failure-status: 101 -// rustc-env:RUST_BACKTRACE=0 -// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" -// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" -// normalize-stderr-test "interpret/intern.rs:[0-9]*:[0-9]*" -> "interpret/intern.rs:LL:CC" - -#![feature(const_fn)] -#![feature(repr_simd)] -#![feature(platform_intrinsics)] -#![allow(non_camel_case_types)] - -#[repr(simd)] struct i8x1(i8); - -extern "platform-intrinsic" { - fn simd_insert(x: T, idx: u32, val: U) -> T; -} - -const X: i8x1 = i8x1(42); - -const fn insert_wrong_scalar() -> i8x1 { - unsafe { simd_insert(X, 0_u32, 42_i16) } -} - -const D: i8x1 = insert_wrong_scalar(); - -fn main() {} diff --git a/src/test/ui/consts/const-eval/simd/insert-fail0.stderr b/src/test/ui/consts/const-eval/simd/insert-fail0.stderr deleted file mode 100644 index 1d0173ed33272..0000000000000 --- a/src/test/ui/consts/const-eval/simd/insert-fail0.stderr +++ /dev/null @@ -1,15 +0,0 @@ -thread 'rustc' panicked at 'assertion failed: `(left == right)` - left: `i16`, - right: `i8`: Scalar type `i16` must match vector element type `i8`', src/librustc_mir/interpret/intrinsics.rs:257:17 -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. - -error: internal compiler error: unexpected panic - -note: the compiler unexpectedly panicked. this is a bug. - -note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports - -note: rustc VERSION running on TARGET - -note: compiler flags: FLAGS - diff --git a/src/test/ui/consts/const-eval/simd/insert-fail1.rs b/src/test/ui/consts/const-eval/simd/insert-fail1.rs deleted file mode 100644 index 146b8ce6a130a..0000000000000 --- a/src/test/ui/consts/const-eval/simd/insert-fail1.rs +++ /dev/null @@ -1,26 +0,0 @@ -// failure-status: 101 -// rustc-env:RUST_BACKTRACE=0 -// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" -// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" -// normalize-stderr-test "interpret/intern.rs:[0-9]*:[0-9]*" -> "interpret/intern.rs:LL:CC" - -#![feature(const_fn)] -#![feature(repr_simd)] -#![feature(platform_intrinsics)] -#![allow(non_camel_case_types)] - -#[repr(simd)] struct i8x1(i8); - -extern "platform-intrinsic" { - fn simd_insert(x: T, idx: u32, val: U) -> T; -} - -const X: i8x1 = i8x1(42); - -const fn insert_wrong_idx() -> i8x1 { - unsafe { simd_insert(X, 1_u32, 42_i8) } -} - -const E: i8x1 = insert_wrong_idx(); - -fn main() {} diff --git a/src/test/ui/consts/const-eval/simd/insert-fail1.stderr b/src/test/ui/consts/const-eval/simd/insert-fail1.stderr deleted file mode 100644 index 6223f308c2f35..0000000000000 --- a/src/test/ui/consts/const-eval/simd/insert-fail1.stderr +++ /dev/null @@ -1,13 +0,0 @@ -thread 'rustc' panicked at 'Index `1` must be in bounds of vector type `i8`: `[0, 1)`', src/librustc_mir/interpret/intrinsics.rs:247:17 -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. - -error: internal compiler error: unexpected panic - -note: the compiler unexpectedly panicked. this is a bug. - -note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports - -note: rustc VERSION running on TARGET - -note: compiler flags: FLAGS - From f359a94849f5a66be4e5058ad9f5a480623a4627 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 25 Sep 2019 08:42:46 -0400 Subject: [PATCH 181/413] Snap cfgs to new beta --- src/liballoc/alloc.rs | 1 - src/liballoc/lib.rs | 1 - src/liballoc/string.rs | 1 - src/liballoc/vec.rs | 3 +-- src/libcore/bool.rs | 1 - src/libcore/clone.rs | 1 - src/libcore/cmp.rs | 4 ---- src/libcore/default.rs | 1 - src/libcore/fmt/mod.rs | 4 +--- src/libcore/hash/mod.rs | 1 - src/libcore/intrinsics.rs | 22 ----------------- src/libcore/lib.rs | 4 ---- src/libcore/macros.rs | 6 ++--- src/libcore/marker.rs | 1 - src/libcore/num/mod.rs | 48 +++++--------------------------------- src/libcore/panicking.rs | 1 - src/libcore/slice/mod.rs | 4 +--- src/libcore/str/mod.rs | 5 +--- src/libproc_macro/lib.rs | 2 +- src/librustc/ty/context.rs | 2 +- src/librustc/ty/mod.rs | 2 +- src/librustc/ty/sty.rs | 2 +- src/librustc_passes/lib.rs | 1 - src/librustdoc/lib.rs | 1 - src/libstd/lib.rs | 1 - src/libsyntax/lib.rs | 1 - 26 files changed, 16 insertions(+), 105 deletions(-) diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index a39fcd5ad4c58..9bc76f51570e1 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -240,7 +240,6 @@ pub(crate) unsafe fn box_free(ptr: Unique) { #[stable(feature = "global_alloc", since = "1.28.0")] #[rustc_allocator_nounwind] pub fn handle_alloc_error(layout: Layout) -> ! { - #[cfg_attr(bootstrap, allow(improper_ctypes))] extern "Rust" { #[lang = "oom"] fn oom_impl(layout: Layout) -> !; diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 9e6ed92ffb567..247cd9a020161 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -117,7 +117,6 @@ #![feature(allocator_internals)] #![feature(on_unimplemented)] #![feature(rustc_const_unstable)] -#![cfg_attr(bootstrap, feature(const_vec_new))] #![feature(slice_partition_dedup)] #![feature(maybe_uninit_extra, maybe_uninit_slice)] #![feature(alloc_layout_extra)] diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index e5f96ada6d5ee..abe50fdb7a396 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -369,7 +369,6 @@ impl String { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_string_new"))] pub const fn new() -> String { String { vec: Vec::new() } } diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 405969a550b88..e5672f8542ff6 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -291,7 +291,7 @@ use crate::raw_vec::RawVec; /// [`reserve`]: ../../std/vec/struct.Vec.html#method.reserve /// [owned slice]: ../../std/boxed/struct.Box.html #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(all(not(bootstrap), not(test)), rustc_diagnostic_item = "vec_type")] +#[cfg_attr(not(test), rustc_diagnostic_item = "vec_type")] pub struct Vec { buf: RawVec, len: usize, @@ -314,7 +314,6 @@ impl Vec { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_vec_new"))] pub const fn new() -> Vec { Vec { buf: RawVec::NEW, diff --git a/src/libcore/bool.rs b/src/libcore/bool.rs index f751ccb428030..617bdd238f4c6 100644 --- a/src/libcore/bool.rs +++ b/src/libcore/bool.rs @@ -1,6 +1,5 @@ //! impl bool {} -#[cfg(not(bootstrap))] #[lang = "bool"] impl bool { /// Returns `Some(t)` if the `bool` is `true`, or `None` otherwise. diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs index 6bdae1b557d61..14d947ccf2402 100644 --- a/src/libcore/clone.rs +++ b/src/libcore/clone.rs @@ -135,7 +135,6 @@ pub trait Clone : Sized { /// Derive macro generating an impl of the trait `Clone`. #[rustc_builtin_macro] -#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_clone_copy)] pub macro Clone($item:item) { /* compiler built-in */ } diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index fc7329f57d45e..d0ea75c7623f4 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -210,7 +210,6 @@ pub trait PartialEq { /// Derive macro generating an impl of the trait `PartialEq`. #[rustc_builtin_macro] -#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro PartialEq($item:item) { /* compiler built-in */ } @@ -273,7 +272,6 @@ pub trait Eq: PartialEq { /// Derive macro generating an impl of the trait `Eq`. #[rustc_builtin_macro] -#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_eq)] pub macro Eq($item:item) { /* compiler built-in */ } @@ -624,7 +622,6 @@ pub trait Ord: Eq + PartialOrd { /// Derive macro generating an impl of the trait `Ord`. #[rustc_builtin_macro] -#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Ord($item:item) { /* compiler built-in */ } @@ -873,7 +870,6 @@ pub trait PartialOrd: PartialEq { /// Derive macro generating an impl of the trait `PartialOrd`. #[rustc_builtin_macro] -#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro PartialOrd($item:item) { /* compiler built-in */ } diff --git a/src/libcore/default.rs b/src/libcore/default.rs index 806d478310760..1aadc77cfb8da 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -117,7 +117,6 @@ pub trait Default: Sized { /// Derive macro generating an impl of the trait `Default`. #[rustc_builtin_macro] -#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Default($item:item) { /* compiler built-in */ } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 65e2f8b9be63f..aafa35873bb65 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -518,8 +518,7 @@ impl Display for Arguments<'_> { label="`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`", )] #[doc(alias = "{:?}")] -#[cfg_attr(bootstrap, lang = "debug_trait")] -#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "debug_trait")] +#[rustc_diagnostic_item = "debug_trait"] pub trait Debug { /// Formats the value using the given formatter. /// @@ -550,7 +549,6 @@ pub trait Debug { pub(crate) mod macros { /// Derive macro generating an impl of the trait `Debug`. #[rustc_builtin_macro] - #[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Debug($item:item) { /* compiler built-in */ } diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index aaaa6f9c575fd..020e085abf8a8 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -202,7 +202,6 @@ pub trait Hash { pub(crate) mod macros { /// Derive macro generating an impl of the trait `Hash`. #[rustc_builtin_macro] - #[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics)] pub macro Hash($item:item) { /* compiler built-in */ } diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 905375eb60fe4..b240d059114eb 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1299,38 +1299,16 @@ extern "rust-intrinsic" { /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_add` method. For example, /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add) - #[cfg(bootstrap)] - pub fn overflowing_add(a: T, b: T) -> T; - /// Returns (a - b) mod 2N, where N is the width of T in bits. - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `wrapping_sub` method. For example, - /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub) - #[cfg(bootstrap)] - pub fn overflowing_sub(a: T, b: T) -> T; - /// Returns (a * b) mod 2N, where N is the width of T in bits. - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `wrapping_mul` method. For example, - /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul) - #[cfg(bootstrap)] - pub fn overflowing_mul(a: T, b: T) -> T; - - /// Returns (a + b) mod 2N, where N is the width of T in bits. - /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `wrapping_add` method. For example, - /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add) - #[cfg(not(bootstrap))] pub fn wrapping_add(a: T, b: T) -> T; /// Returns (a - b) mod 2N, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_sub` method. For example, /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub) - #[cfg(not(bootstrap))] pub fn wrapping_sub(a: T, b: T) -> T; /// Returns (a * b) mod 2N, where N is the width of T in bits. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_mul` method. For example, /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul) - #[cfg(not(bootstrap))] pub fn wrapping_mul(a: T, b: T) -> T; /// Computes `a + b`, while saturating at numeric bounds. diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 8221df56a5142..e8c76b49a8e56 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -87,7 +87,6 @@ #![feature(link_llvm_intrinsics)] #![feature(never_type)] #![feature(nll)] -#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![feature(exhaustive_patterns)] #![feature(no_core)] #![feature(on_unimplemented)] @@ -120,9 +119,6 @@ #![feature(rtm_target_feature)] #![feature(f16c_target_feature)] #![feature(hexagon_target_feature)] -#![cfg_attr(bootstrap, feature(const_slice_len))] -#![cfg_attr(bootstrap, feature(const_str_as_bytes))] -#![cfg_attr(bootstrap, feature(const_str_len))] #![feature(const_int_conversion)] #![feature(const_transmute)] #![feature(non_exhaustive)] diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index c6f5fb0b16350..ef91c3559d8be 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -1236,10 +1236,8 @@ pub(crate) mod builtin { pub macro test($item:item) { /* compiler built-in */ } /// Attribute macro applied to a function to turn it into a benchmark test. - #[cfg_attr(not(bootstrap), unstable(soft, feature = "test", issue = "50297", - reason = "`bench` is a part of custom test frameworks which are unstable"))] - #[cfg_attr(bootstrap, unstable(feature = "test", issue = "50297", - reason = "`bench` is a part of custom test frameworks which are unstable"))] + #[unstable(soft, feature = "test", issue = "50297", + reason = "`bench` is a part of custom test frameworks which are unstable")] #[allow_internal_unstable(test, rustc_attrs)] #[rustc_builtin_macro] pub macro bench($item:item) { /* compiler built-in */ } diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index a2cfb320e7698..7f3d958f5dc80 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -290,7 +290,6 @@ pub trait Copy : Clone { /// Derive macro generating an impl of the trait `Copy`. #[rustc_builtin_macro] -#[cfg_attr(bootstrap, rustc_macro_transparency = "semitransparent")] #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] #[allow_internal_unstable(core_intrinsics, derive_clone_copy)] pub macro Copy($item:item) { /* compiler built-in */ } diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 5d99c10e73815..e9b4efd9c2173 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1112,13 +1112,7 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_add(self, rhs: Self) -> Self { - #[cfg(bootstrap)] { - intrinsics::overflowing_add(self, rhs) - } - - #[cfg(not(bootstrap))] { - intrinsics::wrapping_add(self, rhs) - } + intrinsics::wrapping_add(self, rhs) } } @@ -1141,13 +1135,7 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_sub(self, rhs: Self) -> Self { - #[cfg(bootstrap)] { - intrinsics::overflowing_sub(self, rhs) - } - - #[cfg(not(bootstrap))] { - intrinsics::wrapping_sub(self, rhs) - } + intrinsics::wrapping_sub(self, rhs) } } @@ -1169,13 +1157,7 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_mul(self, rhs: Self) -> Self { - #[cfg(bootstrap)] { - intrinsics::overflowing_mul(self, rhs) - } - - #[cfg(not(bootstrap))] { - intrinsics::wrapping_mul(self, rhs) - } + intrinsics::wrapping_mul(self, rhs) } } @@ -3040,13 +3022,7 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_add(self, rhs: Self) -> Self { - #[cfg(bootstrap)] { - intrinsics::overflowing_add(self, rhs) - } - - #[cfg(not(bootstrap))] { - intrinsics::wrapping_add(self, rhs) - } + intrinsics::wrapping_add(self, rhs) } } @@ -3068,13 +3044,7 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_sub(self, rhs: Self) -> Self { - #[cfg(bootstrap)] { - intrinsics::overflowing_sub(self, rhs) - } - - #[cfg(not(bootstrap))] { - intrinsics::wrapping_sub(self, rhs) - } + intrinsics::wrapping_sub(self, rhs) } } @@ -3097,13 +3067,7 @@ $EndFeature, " without modifying the original"] #[inline] pub const fn wrapping_mul(self, rhs: Self) -> Self { - #[cfg(bootstrap)] { - intrinsics::overflowing_mul(self, rhs) - } - - #[cfg(not(bootstrap))] { - intrinsics::wrapping_mul(self, rhs) - } + intrinsics::wrapping_mul(self, rhs) } doc_comment! { diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index 7b7253419b1bd..e8f0561604aec 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -71,7 +71,6 @@ pub fn panic_fmt(fmt: fmt::Arguments<'_>, file_line_col: &(&'static str, u32, u3 } // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call - #[cfg_attr(bootstrap, allow(improper_ctypes))] extern "Rust" { #[lang = "panic_impl"] fn panic_impl(pi: &PanicInfo<'_>) -> !; diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 0c2a4e086727b..5ec21e6d92862 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -62,9 +62,8 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_slice_len"))] // SAFETY: const sound because we transmute out the length field as a usize (which it must be) - #[cfg_attr(not(bootstrap), allow_internal_unstable(const_fn_union))] + #[allow_internal_unstable(const_fn_union)] pub const fn len(&self) -> usize { unsafe { crate::ptr::Repr { rust: self }.raw.len @@ -81,7 +80,6 @@ impl [T] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_slice_len"))] pub const fn is_empty(&self) -> bool { self.len() == 0 } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index a6ec757faf1d6..ece61dde490fd 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2090,7 +2090,6 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_str_len"))] pub const fn len(&self) -> usize { self.as_bytes().len() } @@ -2110,7 +2109,6 @@ impl str { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_str_len"))] pub const fn is_empty(&self) -> bool { self.len() == 0 } @@ -2168,9 +2166,8 @@ impl str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[inline(always)] - #[cfg_attr(bootstrap, rustc_const_unstable(feature = "const_str_as_bytes"))] // SAFETY: const sound because we transmute two types with the same layout - #[cfg_attr(not(bootstrap), allow_internal_unstable(const_fn_union))] + #[allow_internal_unstable(const_fn_union)] pub const fn as_bytes(&self) -> &[u8] { #[repr(C)] union Slices<'a> { diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index d408fef75153e..d5cdc266acb6a 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -227,7 +227,7 @@ pub mod token_stream { /// To quote `$` itself, use `$$`. #[unstable(feature = "proc_macro_quote", issue = "54722")] #[allow_internal_unstable(proc_macro_def_site)] -#[cfg_attr(not(bootstrap), rustc_builtin_macro)] +#[rustc_builtin_macro] pub macro quote ($($t:tt)*) { /* compiler built-in */ } #[unstable(feature = "proc_macro_internals", issue = "27812")] diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index c03dbb2b1ed0e..a25ef21d6978f 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -974,7 +974,7 @@ pub struct FreeRegionInfo { /// /// [rustc guide]: https://rust-lang.github.io/rustc-guide/ty.html #[derive(Copy, Clone)] -#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "TyCtxt")] +#[rustc_diagnostic_item = "TyCtxt"] pub struct TyCtxt<'tcx> { gcx: &'tcx GlobalCtxt<'tcx>, } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index ef8bdfb583edf..61483fa8a498e 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -581,7 +581,7 @@ impl<'a, 'tcx> HashStable> for ty::TyS<'tcx> { } } -#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "Ty")] +#[rustc_diagnostic_item = "Ty"] pub type Ty<'tcx> = &'tcx TyS<'tcx>; impl<'tcx> rustc_serialize::UseSpecializedEncodable for Ty<'tcx> {} diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index e73a51e6f78e5..036f41a4043d4 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -86,7 +86,7 @@ impl BoundRegion { /// AST structure in `libsyntax/ast.rs` as well. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable, Debug)] -#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "TyKind")] +#[rustc_diagnostic_item = "TyKind"] pub enum TyKind<'tcx> { /// The primitive boolean type. Written as `bool`. Bool, diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index a5a8315a1e73f..4e29706714f3d 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -8,7 +8,6 @@ #![feature(in_band_lifetimes)] #![feature(nll)] -#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![recursion_limit="256"] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 0b9e717221f2d..2985e7f70b52f 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -1,7 +1,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/")] -#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![feature(rustc_private)] #![feature(arbitrary_self_types)] #![feature(box_patterns)] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 21aeb9c26f83c..5d9683f8deda9 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -238,7 +238,6 @@ #![feature(array_error_internals)] #![feature(asm)] #![feature(associated_type_bounds)] -#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![feature(box_syntax)] #![feature(c_variadic)] #![feature(cfg_target_has_atomic)] diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index b0833010fe071..2c10220c766a8 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -7,7 +7,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))] -#![cfg_attr(bootstrap, feature(bind_by_move_pattern_guards))] #![feature(box_syntax)] #![feature(const_fn)] #![feature(const_transmute)] From 33b89a39181b2f5cda8b28320c764ca733f9344a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 14 Sep 2019 15:13:41 +0200 Subject: [PATCH 182/413] Add long error explanation for E0531 --- src/librustc_resolve/error_codes.rs | 46 ++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index adbff67cc8dac..9a39fcf422393 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1525,6 +1525,51 @@ match r { ``` "##, +E0531: r##" +An unknown tuple struct/variant has been used. + +Erroneous code example: + +```compile_fail,E0531 +let Type(x) = Type(12); // error! +match Bar(12) { + Bar(x) => {} // error! + _ => {} +} +``` + +In most cases, it's either a forgotten import or a typo. However, let's look at +how you can have such a type: + +```edition2018 +struct Type(u32); // this is a tuple struct + +enum Foo { + Bar(u32), // this is a tuple variant +} + +use Foo::*; // To use Foo's variant directly, we need to import them in + // the scope. +``` + +Either way, it should work fine with our previous code: + +```edition2018 +struct Type(u32); + +enum Foo { + Bar(u32), +} +use Foo::*; + +let Type(x) = Type(12); // ok! +match Type(12) { + Type(x) => {} // ok! + _ => {} +} +``` +"##, + E0532: r##" Pattern arm did not match expected kind. @@ -1675,7 +1720,6 @@ fn const_id() -> T { // error: const parameter // E0419, merged into 531 // E0420, merged into 532 // E0421, merged into 531 - E0531, // unresolved pattern path kind `name` // E0427, merged into 530 // E0467, removed // E0470, removed From 2fd38115095f199112ab1775f2d77cb99fba17d0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 14 Sep 2019 16:22:14 +0200 Subject: [PATCH 183/413] update ui tests --- src/test/ui/enums-pats-not-idents.stderr | 1 + src/test/ui/issues/issue-5927.stderr | 3 ++- src/test/ui/keyword/keyword-self-as-identifier.stderr | 1 + src/test/ui/resolve/resolve-assoc-suggestions.stderr | 2 +- src/test/ui/self/self_type_keyword-2.stderr | 3 ++- src/test/ui/self/self_type_keyword.stderr | 3 ++- 6 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/test/ui/enums-pats-not-idents.stderr b/src/test/ui/enums-pats-not-idents.stderr index 3891d1eac487b..6b1e6046260a9 100644 --- a/src/test/ui/enums-pats-not-idents.stderr +++ b/src/test/ui/enums-pats-not-idents.stderr @@ -6,3 +6,4 @@ LL | let a(1) = 13; error: aborting due to previous error +For more information about this error, try `rustc --explain E0531`. diff --git a/src/test/ui/issues/issue-5927.stderr b/src/test/ui/issues/issue-5927.stderr index 89f5e399ae689..3d4550ec8b238 100644 --- a/src/test/ui/issues/issue-5927.stderr +++ b/src/test/ui/issues/issue-5927.stderr @@ -12,4 +12,5 @@ LL | x(1) => x(1) error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0425`. +Some errors have detailed explanations: E0425, E0531. +For more information about an error, try `rustc --explain E0425`. diff --git a/src/test/ui/keyword/keyword-self-as-identifier.stderr b/src/test/ui/keyword/keyword-self-as-identifier.stderr index 5f567910ed81b..be57c6ad26fd8 100644 --- a/src/test/ui/keyword/keyword-self-as-identifier.stderr +++ b/src/test/ui/keyword/keyword-self-as-identifier.stderr @@ -6,3 +6,4 @@ LL | let Self = 22; error: aborting due to previous error +For more information about this error, try `rustc --explain E0531`. diff --git a/src/test/ui/resolve/resolve-assoc-suggestions.stderr b/src/test/ui/resolve/resolve-assoc-suggestions.stderr index 87040015b8d80..f3b8909ab2236 100644 --- a/src/test/ui/resolve/resolve-assoc-suggestions.stderr +++ b/src/test/ui/resolve/resolve-assoc-suggestions.stderr @@ -54,5 +54,5 @@ LL | method; error: aborting due to 9 previous errors -Some errors have detailed explanations: E0412, E0425. +Some errors have detailed explanations: E0412, E0425, E0531. For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/self/self_type_keyword-2.stderr b/src/test/ui/self/self_type_keyword-2.stderr index 359410bc1cd6a..560c6d2199ca0 100644 --- a/src/test/ui/self/self_type_keyword-2.stderr +++ b/src/test/ui/self/self_type_keyword-2.stderr @@ -24,4 +24,5 @@ LL | Foo { x: Self } => (), error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0432`. +Some errors have detailed explanations: E0432, E0531. +For more information about an error, try `rustc --explain E0432`. diff --git a/src/test/ui/self/self_type_keyword.stderr b/src/test/ui/self/self_type_keyword.stderr index bb631194bf3df..431056e45f5b3 100644 --- a/src/test/ui/self/self_type_keyword.stderr +++ b/src/test/ui/self/self_type_keyword.stderr @@ -80,4 +80,5 @@ LL | struct Bar<'Self>; error: aborting due to 12 previous errors -For more information about this error, try `rustc --explain E0392`. +Some errors have detailed explanations: E0392, E0531. +For more information about an error, try `rustc --explain E0392`. From 2808a46a497959f00fcca87d7874118616356a18 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 16 Sep 2019 18:59:31 +0100 Subject: [PATCH 184/413] Rename non-`TyS` uses of `sty` --- src/librustc/traits/specialize/specialization_graph.rs | 4 ++-- src/librustc_mir/interpret/cast.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index c9a40db41dfde..885d4b4cb0269 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -249,8 +249,8 @@ impl<'tcx> Children { self.blanket_impls.iter().chain(nonblanket).cloned() } - fn filtered(&mut self, sty: SimplifiedType) -> impl Iterator + '_ { - let nonblanket = self.nonblanket_impls.entry(sty).or_default().iter(); + fn filtered(&mut self, st: SimplifiedType) -> impl Iterator + '_ { + let nonblanket = self.nonblanket_impls.entry(st).or_default().iter(); self.blanket_impls.iter().chain(nonblanket).cloned() } } diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 210647ac1e9a3..2797766f2171e 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -244,12 +244,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { src: OpTy<'tcx, M::PointerTag>, dest: PlaceTy<'tcx, M::PointerTag>, // The pointee types - sty: Ty<'tcx>, - dty: Ty<'tcx>, + source_ty: Ty<'tcx>, + dest_ty: Ty<'tcx>, ) -> InterpResult<'tcx> { // A -> A conversion let (src_pointee_ty, dest_pointee_ty) = - self.tcx.struct_lockstep_tails_erasing_lifetimes(sty, dty, self.param_env); + self.tcx.struct_lockstep_tails_erasing_lifetimes(source_ty, dest_ty, self.param_env); match (&src_pointee_ty.sty, &dest_pointee_ty.sty) { (&ty::Array(_, length), &ty::Slice(_)) => { From e2e0f9af85cbe9c79a04b963df9e87c719339e0e Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 16 Sep 2019 19:08:35 +0100 Subject: [PATCH 185/413] Rename `sty` to `kind` --- src/librustc/infer/canonical/canonicalizer.rs | 2 +- .../infer/canonical/query_response.rs | 2 +- src/librustc/infer/combine.rs | 4 +- src/librustc/infer/equate.rs | 2 +- src/librustc/infer/error_reporting/mod.rs | 18 ++-- .../infer/error_reporting/need_type_info.rs | 8 +- .../error_reporting/nice_region_error/util.rs | 2 +- src/librustc/infer/freshen.rs | 2 +- src/librustc/infer/fudge.rs | 2 +- src/librustc/infer/lattice.rs | 2 +- src/librustc/infer/mod.rs | 6 +- src/librustc/infer/nll_relate/mod.rs | 8 +- src/librustc/infer/opaque_types/mod.rs | 6 +- src/librustc/infer/outlives/obligations.rs | 2 +- src/librustc/infer/outlives/verify.rs | 4 +- src/librustc/infer/resolve.rs | 4 +- src/librustc/infer/sub.rs | 2 +- src/librustc/infer/type_variable.rs | 2 +- src/librustc/lint/context.rs | 2 +- src/librustc/middle/dead.rs | 6 +- src/librustc/middle/expr_use_visitor.rs | 8 +- src/librustc/middle/intrinsicck.rs | 4 +- src/librustc/middle/mem_categorization.rs | 12 +-- src/librustc/mir/tcx.rs | 6 +- src/librustc/traits/auto_trait.rs | 4 +- src/librustc/traits/coherence.rs | 8 +- src/librustc/traits/error_reporting.rs | 22 ++-- src/librustc/traits/fulfill.rs | 2 +- src/librustc/traits/object_safety.rs | 2 +- src/librustc/traits/project.rs | 6 +- src/librustc/traits/query/dropck_outlives.rs | 2 +- src/librustc/traits/query/normalize.rs | 2 +- src/librustc/traits/select.rs | 32 +++--- src/librustc/traits/structural_impls.rs | 2 +- src/librustc/ty/_match.rs | 2 +- src/librustc/ty/cast.rs | 2 +- src/librustc/ty/codec.rs | 2 +- src/librustc/ty/context.rs | 16 +-- src/librustc/ty/error.rs | 4 +- src/librustc/ty/fast_reject.rs | 2 +- src/librustc/ty/fold.rs | 6 +- src/librustc/ty/inhabitedness/mod.rs | 2 +- src/librustc/ty/instance.rs | 4 +- src/librustc/ty/layout.rs | 24 ++--- src/librustc/ty/mod.rs | 20 ++-- src/librustc/ty/outlives.rs | 2 +- src/librustc/ty/print/mod.rs | 2 +- src/librustc/ty/print/obsolete.rs | 2 +- src/librustc/ty/print/pretty.rs | 14 +-- src/librustc/ty/relate.rs | 2 +- src/librustc/ty/structural_impls.rs | 6 +- src/librustc/ty/sty.rs | 102 +++++++++--------- src/librustc/ty/subst.rs | 2 +- src/librustc/ty/util.rs | 36 +++---- src/librustc/ty/walk.rs | 2 +- src/librustc/ty/wf.rs | 4 +- .../borrowck/check_loans.rs | 2 +- .../borrowck/gather_loans/gather_moves.rs | 2 +- .../borrowck/gather_loans/restrictions.rs | 2 +- .../borrowck/move_data.rs | 4 +- src/librustc_codegen_llvm/builder.rs | 2 +- src/librustc_codegen_llvm/consts.rs | 2 +- .../debuginfo/metadata.rs | 28 ++--- src/librustc_codegen_llvm/debuginfo/mod.rs | 8 +- src/librustc_codegen_llvm/intrinsic.rs | 52 ++++----- src/librustc_codegen_llvm/type_of.rs | 10 +- src/librustc_codegen_ssa/base.rs | 8 +- .../debuginfo/type_names.rs | 2 +- src/librustc_codegen_ssa/glue.rs | 4 +- src/librustc_codegen_ssa/mir/analyze.rs | 2 +- src/librustc_codegen_ssa/mir/block.rs | 4 +- src/librustc_codegen_ssa/mir/constant.rs | 2 +- src/librustc_codegen_ssa/mir/mod.rs | 14 +-- src/librustc_codegen_ssa/mir/place.rs | 2 +- src/librustc_codegen_ssa/mir/rvalue.rs | 6 +- src/librustc_codegen_ssa/traits/type_.rs | 2 +- .../symbol_names/legacy.rs | 6 +- src/librustc_codegen_utils/symbol_names/v0.rs | 6 +- src/librustc_lint/builtin.rs | 4 +- src/librustc_lint/types.rs | 16 +-- src/librustc_lint/unused.rs | 2 +- src/librustc_metadata/encoder.rs | 4 +- .../borrow_check/conflict_errors.rs | 20 ++-- .../borrow_check/error_reporting.rs | 14 +-- src/librustc_mir/borrow_check/mod.rs | 6 +- src/librustc_mir/borrow_check/move_errors.rs | 2 +- .../borrow_check/mutability_errors.rs | 6 +- .../borrow_check/nll/explain_borrow/mod.rs | 4 +- .../nll/region_infer/error_reporting/mod.rs | 2 +- .../error_reporting/region_name.rs | 2 +- .../borrow_check/nll/type_check/mod.rs | 36 +++---- .../borrow_check/nll/universal_regions.rs | 4 +- src/librustc_mir/borrow_check/place_ext.rs | 2 +- .../borrow_check/places_conflict.rs | 6 +- src/librustc_mir/borrow_check/prefixes.rs | 2 +- src/librustc_mir/build/expr/into.rs | 2 +- src/librustc_mir/build/matches/simplify.rs | 2 +- src/librustc_mir/build/matches/test.rs | 8 +- src/librustc_mir/build/mod.rs | 6 +- src/librustc_mir/const_eval.rs | 4 +- .../dataflow/drop_flag_effects.rs | 2 +- .../dataflow/move_paths/builder.rs | 4 +- src/librustc_mir/hair/constant.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 10 +- src/librustc_mir/hair/pattern/_match.rs | 38 +++---- src/librustc_mir/hair/pattern/check_match.rs | 8 +- src/librustc_mir/hair/pattern/mod.rs | 28 ++--- src/librustc_mir/hair/util.rs | 2 +- src/librustc_mir/interpret/cast.rs | 16 +-- src/librustc_mir/interpret/eval_context.rs | 2 +- src/librustc_mir/interpret/intern.rs | 6 +- .../interpret/intrinsics/type_name.rs | 2 +- src/librustc_mir/interpret/operand.rs | 2 +- src/librustc_mir/interpret/operator.rs | 4 +- src/librustc_mir/interpret/place.rs | 6 +- src/librustc_mir/interpret/terminator.rs | 6 +- src/librustc_mir/interpret/validity.rs | 12 +-- src/librustc_mir/interpret/visitor.rs | 2 +- src/librustc_mir/lints.rs | 2 +- src/librustc_mir/monomorphize/collector.rs | 10 +- src/librustc_mir/shim.rs | 6 +- src/librustc_mir/transform/add_retag.rs | 2 +- src/librustc_mir/transform/check_unsafety.rs | 6 +- src/librustc_mir/transform/const_prop.rs | 6 +- src/librustc_mir/transform/generator.rs | 4 +- src/librustc_mir/transform/inline.rs | 6 +- src/librustc_mir/transform/instcombine.rs | 2 +- src/librustc_mir/transform/qualify_consts.rs | 20 ++-- .../transform/qualify_min_const_fn.rs | 6 +- src/librustc_mir/transform/rustc_peek.rs | 2 +- .../transform/uniform_array_move_out.rs | 4 +- src/librustc_mir/util/alignment.rs | 2 +- src/librustc_mir/util/borrowck_errors.rs | 2 +- src/librustc_mir/util/elaborate_drops.rs | 2 +- src/librustc_passes/rvalue_promotion.rs | 6 +- src/librustc_privacy/lib.rs | 4 +- src/librustc_save_analysis/lib.rs | 6 +- src/librustc_traits/chalk_context/mod.rs | 2 +- .../chalk_context/program_clauses/builtin.rs | 8 +- .../chalk_context/program_clauses/mod.rs | 2 +- .../chalk_context/resolvent_ops.rs | 4 +- src/librustc_traits/dropck_outlives.rs | 4 +- src/librustc_traits/lowering/environment.rs | 2 +- src/librustc_typeck/astconv.rs | 4 +- src/librustc_typeck/check/autoderef.rs | 2 +- src/librustc_typeck/check/callee.rs | 6 +- src/librustc_typeck/check/cast.rs | 12 +-- src/librustc_typeck/check/closure.rs | 4 +- src/librustc_typeck/check/coercion.rs | 26 ++--- src/librustc_typeck/check/demand.rs | 12 +-- src/librustc_typeck/check/dropck.rs | 2 +- src/librustc_typeck/check/expr.rs | 34 +++--- src/librustc_typeck/check/method/confirm.rs | 8 +- src/librustc_typeck/check/method/mod.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 12 +-- src/librustc_typeck/check/method/suggest.rs | 12 +-- src/librustc_typeck/check/mod.rs | 56 +++++----- src/librustc_typeck/check/op.rs | 28 ++--- src/librustc_typeck/check/pat.rs | 24 ++--- src/librustc_typeck/check/regionck.rs | 12 +-- src/librustc_typeck/check/upvar.rs | 2 +- src/librustc_typeck/check/wfcheck.rs | 8 +- src/librustc_typeck/check/writeback.rs | 4 +- src/librustc_typeck/coherence/builtin.rs | 6 +- .../coherence/inherent_impls.rs | 2 +- src/librustc_typeck/coherence/mod.rs | 2 +- src/librustc_typeck/coherence/orphan.rs | 2 +- src/librustc_typeck/collect.rs | 10 +- .../constrained_generic_params.rs | 2 +- src/librustc_typeck/lib.rs | 4 +- .../outlives/implicit_infer.rs | 2 +- src/librustc_typeck/variance/constraints.rs | 4 +- src/librustc_typeck/variance/solve.rs | 2 +- src/librustdoc/clean/blanket_impl.rs | 2 +- src/librustdoc/clean/mod.rs | 20 ++-- .../passes/collect_intra_doc_links.rs | 2 +- 176 files changed, 691 insertions(+), 691 deletions(-) diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc/infer/canonical/canonicalizer.rs index db724875b8aa3..bd003735a892c 100644 --- a/src/librustc/infer/canonical/canonicalizer.rs +++ b/src/librustc/infer/canonical/canonicalizer.rs @@ -343,7 +343,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - match t.sty { + match t.kind { ty::Infer(ty::TyVar(vid)) => { debug!("canonical: type var found with vid {:?}", vid); match self.infcx.unwrap().probe_ty_var(vid) { diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc/infer/canonical/query_response.rs index 79c5538626be1..ae1624fc5a242 100644 --- a/src/librustc/infer/canonical/query_response.rs +++ b/src/librustc/infer/canonical/query_response.rs @@ -471,7 +471,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { match result_value.unpack() { UnpackedKind::Type(result_value) => { // e.g., here `result_value` might be `?0` in the example above... - if let ty::Bound(debruijn, b) = result_value.sty { + if let ty::Bound(debruijn, b) = result_value.kind { // ...in which case we would set `canonical_vars[0]` to `Some(?U)`. // We only allow a `ty::INNERMOST` index in substitutions. diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 966c5810171af..6f73275d455f5 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -70,7 +70,7 @@ impl<'infcx, 'tcx> InferCtxt<'infcx, 'tcx> { { let a_is_expected = relation.a_is_expected(); - match (&a.sty, &b.sty) { + match (&a.kind, &b.kind) { // Relate integral variables to other types (&ty::Infer(ty::IntVar(a_id)), &ty::Infer(ty::IntVar(b_id))) => { self.int_unification_table @@ -486,7 +486,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> { // any other type variable related to `vid` via // subtyping. This is basically our "occurs check", preventing // us from creating infinitely sized types. - match t.sty { + match t.kind { ty::Infer(ty::TyVar(vid)) => { let mut variables = self.infcx.type_variables.borrow_mut(); let vid = variables.root_var(vid); diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs index 6065387647fa7..aea58acab5450 100644 --- a/src/librustc/infer/equate.rs +++ b/src/librustc/infer/equate.rs @@ -68,7 +68,7 @@ impl TypeRelation<'tcx> for Equate<'combine, 'infcx, 'tcx> { debug!("{}.tys: replacements ({:?}, {:?})", self.tag(), a, b); - match (&a.sty, &b.sty) { + match (&a.kind, &b.kind) { (&ty::Infer(TyVar(a_id)), &ty::Infer(TyVar(b_id))) => { infcx.type_variables.borrow_mut().equate(a_id, b_id); } diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 0b6740d7bbbc8..15a664cb33b6f 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -589,7 +589,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // if they are both "path types", there's a chance of ambiguity // due to different versions of the same crate if let (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _)) - = (&exp_found.expected.sty, &exp_found.found.sty) + = (&exp_found.expected.kind, &exp_found.found.kind) { report_path_match(err, exp_adt.did, found_adt.did); } @@ -803,7 +803,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty); return Some(()); } - if let &ty::Adt(def, _) = &ta.sty { + if let &ty::Adt(def, _) = &ta.kind { let path_ = self.tcx.def_path_str(def.did.clone()); if path_ == other_path { self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty); @@ -868,7 +868,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// relevant differences, and return two representation of those types for highlighted printing. fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> (DiagnosticStyledString, DiagnosticStyledString) { fn equals<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { - match (&a.sty, &b.sty) { + match (&a.kind, &b.kind) { (a, b) if *a == *b => true, (&ty::Int(_), &ty::Infer(ty::InferTy::IntVar(_))) | (&ty::Infer(ty::InferTy::IntVar(_)), &ty::Int(_)) @@ -902,7 +902,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { s.push_normal(ty.to_string()); } - match (&t1.sty, &t2.sty) { + match (&t1.kind, &t2.kind) { (&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => { let sub_no_defaults_1 = self.strip_generic_default_params(def1.did, sub1); let sub_no_defaults_2 = self.strip_generic_default_params(def2.did, sub2); @@ -1138,7 +1138,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { match (terr, is_simple_error, expected == found) { (&TypeError::Sorts(ref values), false, true) => { let sort_string = | a_type: Ty<'tcx> | - if let ty::Opaque(def_id, _) = a_type.sty { + if let ty::Opaque(def_id, _) = a_type.kind { format!(" (opaque type at {})", self.tcx.sess.source_map() .mk_substr_filename(self.tcx.def_span(def_id))) } else { @@ -1179,9 +1179,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { exp_found: &ty::error::ExpectedFound>, diag: &mut DiagnosticBuilder<'tcx>, ) { - match (&exp_found.expected.sty, &exp_found.found.sty) { + match (&exp_found.expected.kind, &exp_found.found.kind) { (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) => { - if let ty::Adt(found_def, found_substs) = found_ty.sty { + if let ty::Adt(found_def, found_substs) = found_ty.kind { let path_str = format!("{:?}", exp_def); if exp_def == &found_def { let opt_msg = "you can convert from `&Option` to `Option<&T>` using \ @@ -1203,9 +1203,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { { let mut show_suggestion = true; for (exp_ty, found_ty) in exp_substs.types().zip(found_substs.types()) { - match exp_ty.sty { + match exp_ty.kind { ty::Ref(_, exp_ty, _) => { - match (&exp_ty.sty, &found_ty.sty) { + match (&exp_ty.kind, &found_ty.kind) { (_, ty::Param(_)) | (_, ty::Infer(_)) | (ty::Param(_), _) | diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 7068fe3601a62..d56a6cf1f7bcb 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -44,7 +44,7 @@ impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> { Some(ty) => { let ty = self.infcx.resolve_vars_if_possible(&ty); if ty.walk().any(|inner_ty| { - inner_ty == self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) { + inner_ty == self.target_ty || match (&inner_ty.kind, &self.target_ty.kind) { (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => { self.infcx .type_variables @@ -151,7 +151,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ty: Ty<'tcx>, highlight: Option, ) -> (String, Option) { - if let ty::Infer(ty::TyVar(ty_vid)) = ty.sty { + if let ty::Infer(ty::TyVar(ty_vid)) = ty.kind { let ty_vars = self.type_variables.borrow(); let var_origin = ty_vars.var_origin(ty_vid); if let TypeVariableOriginKind::TypeParameterDefinition(name) = var_origin.kind { @@ -219,7 +219,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }; let ty_msg = match local_visitor.found_ty { - Some(ty::TyS { sty: ty::Closure(def_id, substs), .. }) => { + Some(ty::TyS { kind: ty::Closure(def_id, substs), .. }) => { let fn_sig = substs.closure_sig(*def_id, self.tcx); let args = closure_args(&fn_sig); let ret = fn_sig.output().skip_binder().to_string(); @@ -254,7 +254,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); let suffix = match local_visitor.found_ty { - Some(ty::TyS { sty: ty::Closure(def_id, substs), .. }) => { + Some(ty::TyS { kind: ty::Closure(def_id, substs), .. }) => { let fn_sig = substs.closure_sig(*def_id, self.tcx); let ret = fn_sig.output().skip_binder().to_string(); diff --git a/src/librustc/infer/error_reporting/nice_region_error/util.rs b/src/librustc/infer/error_reporting/nice_region_error/util.rs index 668c99da0034f..a2e48cf07cb7c 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/util.rs @@ -109,7 +109,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { decl: &hir::FnDecl, ) -> Option { let ret_ty = self.tcx().type_of(scope_def_id); - if let ty::FnDef(_, _) = ret_ty.sty { + if let ty::FnDef(_, _) = ret_ty.kind { let sig = ret_ty.fn_sig(self.tcx()); let late_bound_regions = self.tcx() .collect_referenced_late_bound_regions(&sig.output()); diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index 400a538baa965..9e9220cc3d8cc 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -153,7 +153,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { let tcx = self.infcx.tcx; - match t.sty { + match t.kind { ty::Infer(ty::TyVar(v)) => { let opt_ty = self.infcx.type_variables.borrow_mut().probe(v).known(); self.freshen_ty( diff --git a/src/librustc/infer/fudge.rs b/src/librustc/infer/fudge.rs index 658a9c1d88805..e27766f461697 100644 --- a/src/librustc/infer/fudge.rs +++ b/src/librustc/infer/fudge.rs @@ -148,7 +148,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for InferenceFudger<'a, 'tcx> { } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - match ty.sty { + match ty.kind { ty::Infer(ty::InferTy::TyVar(vid)) => { if self.type_vars.0.contains(&vid) { // This variable was created during the fudging. diff --git a/src/librustc/infer/lattice.rs b/src/librustc/infer/lattice.rs index 68cbef4407677..39701231aad7e 100644 --- a/src/librustc/infer/lattice.rs +++ b/src/librustc/infer/lattice.rs @@ -61,7 +61,7 @@ where let infcx = this.infcx(); let a = infcx.type_variables.borrow_mut().replace_if_possible(a); let b = infcx.type_variables.borrow_mut().replace_if_possible(b); - match (&a.sty, &b.sty) { + match (&a.kind, &b.kind) { // If one side is known to be a variable and one is not, // create a variable (`v`) to represent the LUB. Make sure to // relate `v` to the non-type-variable first (by passing it diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 5d556485c15f3..b715598ef80f0 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -614,7 +614,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } pub fn type_var_diverges(&'a self, ty: Ty<'_>) -> bool { - match ty.sty { + match ty.kind { ty::Infer(ty::TyVar(vid)) => self.type_variables.borrow().var_diverges(vid), _ => false, } @@ -627,7 +627,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn type_is_unconstrained_numeric(&'a self, ty: Ty<'_>) -> UnconstrainedNumeric { use crate::ty::error::UnconstrainedNumeric::Neither; use crate::ty::error::UnconstrainedNumeric::{UnconstrainedFloat, UnconstrainedInt}; - match ty.sty { + match ty.kind { ty::Infer(ty::IntVar(vid)) => { if self.int_unification_table .borrow_mut() @@ -1563,7 +1563,7 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> { } pub fn shallow_resolve(&mut self, typ: Ty<'tcx>) -> Ty<'tcx> { - match typ.sty { + match typ.kind { ty::Infer(ty::TyVar(v)) => { // Not entirely obvious: if `typ` is a type variable, // it can be resolved to an int/float variable, which diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc/infer/nll_relate/mod.rs index 5d521def65b0b..50a2c95ed6f22 100644 --- a/src/librustc/infer/nll_relate/mod.rs +++ b/src/librustc/infer/nll_relate/mod.rs @@ -274,7 +274,7 @@ where use crate::traits::WhereClause; use syntax_pos::DUMMY_SP; - match value_ty.sty { + match value_ty.kind { ty::Projection(other_projection_ty) => { let var = self.infcx.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, @@ -328,7 +328,7 @@ where // This only presently applies to chalk integration, as NLL // doesn't permit type variables to appear on both sides (and // doesn't use lazy norm). - match value_ty.sty { + match value_ty.kind { ty::Infer(ty::TyVar(value_vid)) => { // Two type variables: just equate them. self.infcx @@ -548,7 +548,7 @@ where b = self.infcx.shallow_resolve(b); } - match (&a.sty, &b.sty) { + match (&a.kind, &b.kind) { (_, &ty::Infer(ty::TyVar(vid))) => { if D::forbid_inference_vars() { // Forbid inference variables in the RHS. @@ -878,7 +878,7 @@ where debug!("TypeGeneralizer::tys(a={:?})", a); - match a.sty { + match a.kind { ty::Infer(ty::TyVar(_)) | ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) if D::forbid_inference_vars() => { diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 129cfc8bcb23f..9b447f192a97a 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -720,7 +720,7 @@ where return false; // keep visiting } - match ty.sty { + match ty.kind { ty::Closure(def_id, ref substs) => { // Skip lifetime parameters of the enclosing item(s) @@ -857,7 +857,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - match ty.sty { + match ty.kind { ty::Closure(def_id, substs) => { // I am a horrible monster and I pray for death. When // we encounter a closure here, it is always a closure @@ -990,7 +990,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> { ty_op: |ty| { if ty.references_error() { return tcx.types.err; - } else if let ty::Opaque(def_id, substs) = ty.sty { + } else if let ty::Opaque(def_id, substs) = ty.kind { // Check that this is `impl Trait` type is // declared by `parent_def_id` -- i.e., one whose // value we are inferring. At present, this is diff --git a/src/librustc/infer/outlives/obligations.rs b/src/librustc/infer/outlives/obligations.rs index e1470e4ef0232..df491aef54fb9 100644 --- a/src/librustc/infer/outlives/obligations.rs +++ b/src/librustc/infer/outlives/obligations.rs @@ -403,7 +403,7 @@ where // 'a` in the environment but `trait Foo<'b> { type Item: 'b // }` in the trait definition. approx_env_bounds.retain(|bound| { - match bound.0.sty { + match bound.0.kind { ty::Projection(projection_ty) => { self.verify_bound.projection_declared_bounds_from_trait(projection_ty) .all(|r| r != bound.1) diff --git a/src/librustc/infer/outlives/verify.rs b/src/librustc/infer/outlives/verify.rs index f23e52fcfe499..3110b027c5bbe 100644 --- a/src/librustc/infer/outlives/verify.rs +++ b/src/librustc/infer/outlives/verify.rs @@ -44,7 +44,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { } fn type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> { - match ty.sty { + match ty.kind { ty::Param(p) => self.param_bound(p), ty::Projection(data) => self.projection_bound(data), _ => self.recursive_type_bound(ty), @@ -87,7 +87,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { let projection_ty = GenericKind::Projection(projection_ty).to_ty(self.tcx); let erased_projection_ty = self.tcx.erase_regions(&projection_ty); self.declared_generic_bounds_from_env_with_compare_fn(|ty| { - if let ty::Projection(..) = ty.sty { + if let ty::Projection(..) = ty.kind { let erased_ty = self.tcx.erase_regions(&ty); erased_ty == erased_projection_ty } else { diff --git a/src/librustc/infer/resolve.rs b/src/librustc/infer/resolve.rs index 7e553d7666b22..2db18674e2f53 100644 --- a/src/librustc/infer/resolve.rs +++ b/src/librustc/infer/resolve.rs @@ -118,7 +118,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> { fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { let t = self.infcx.shallow_resolve(t); if t.has_infer_types() { - if let ty::Infer(infer_ty) = t.sty { + if let ty::Infer(infer_ty) = t.kind { // Since we called `shallow_resolve` above, this must // be an (as yet...) unresolved inference variable. let ty_var_span = @@ -188,7 +188,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { // defaulted tuples. } else { let t = self.infcx.shallow_resolve(t); - match t.sty { + match t.kind { ty::Infer(ty::TyVar(vid)) => { self.err = Some(FixupError::UnresolvedTy(vid)); self.tcx().types.err diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs index 67c97ef5d8b29..21c847e80f413 100644 --- a/src/librustc/infer/sub.rs +++ b/src/librustc/infer/sub.rs @@ -71,7 +71,7 @@ impl TypeRelation<'tcx> for Sub<'combine, 'infcx, 'tcx> { let infcx = self.fields.infcx; let a = infcx.type_variables.borrow_mut().replace_if_possible(a); let b = infcx.type_variables.borrow_mut().replace_if_possible(b); - match (&a.sty, &b.sty) { + match (&a.kind, &b.kind) { (&ty::Infer(TyVar(a_vid)), &ty::Infer(TyVar(b_vid))) => { // Shouldn't have any LBR here, so we can safely put // this under a binder below without fear of accidental diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index dd09e9a8f58a4..ce1b54bb1c81d 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -247,7 +247,7 @@ impl<'tcx> TypeVariableTable<'tcx> { /// instantiated, then return the with which it was /// instantiated. Otherwise, returns `t`. pub fn replace_if_possible(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - match t.sty { + match t.kind { ty::Infer(ty::TyVar(v)) => { match self.probe(v) { TypeVariableValue::Unknown { .. } => t, diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index c658120b95df3..7508dbe6c8aea 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -829,7 +829,7 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> { trait_ref: Option>, ) -> Result { if trait_ref.is_none() { - if let ty::Adt(def, substs) = self_ty.sty { + if let ty::Adt(def, substs) = self_ty.kind { return self.print_def_path(def.did, substs); } } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index d4805a7c78322..1debf0e2b73c5 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -117,7 +117,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } fn handle_field_access(&mut self, lhs: &hir::Expr, hir_id: hir::HirId) { - match self.tables.expr_ty_adjusted(lhs).sty { + match self.tables.expr_ty_adjusted(lhs).kind { ty::Adt(def, _) => { let index = self.tcx.field_index(hir_id, self.tables); self.insert_def_id(def.non_enum_variant().fields[index].did); @@ -128,7 +128,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, res: Res, pats: &[hir::FieldPat]) { - let variant = match self.tables.node_type(lhs.hir_id).sty { + let variant = match self.tables.node_type(lhs.hir_id).kind { ty::Adt(adt, _) => adt.variant_of_res(res), _ => span_bug!(lhs.span, "non-ADT in struct pattern") }; @@ -248,7 +248,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { self.handle_field_access(&lhs, expr.hir_id); } hir::ExprKind::Struct(_, ref fields, _) => { - if let ty::Adt(ref adt, _) = self.tables.expr_ty(expr).sty { + if let ty::Adt(ref adt, _) = self.tables.expr_ty(expr).kind { self.mark_as_used_if_union(adt, fields); } } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index de6dadabcbf56..b0a9af6af0fd0 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -455,7 +455,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // make sure that the thing we are pointing out stays valid // for the lifetime `scope_r` of the resulting ptr: let expr_ty = return_if_err!(self.mc.expr_ty(expr)); - if let ty::Ref(r, _, _) = expr_ty.sty { + if let ty::Ref(r, _, _) = expr_ty.kind { let bk = ty::BorrowKind::from_mutbl(m); self.borrow_expr(&base, r, bk, AddrOf); } @@ -553,7 +553,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { let callee_ty = return_if_err!(self.mc.expr_ty_adjusted(callee)); debug!("walk_callee: callee={:?} callee_ty={:?}", callee, callee_ty); - match callee_ty.sty { + match callee_ty.kind { ty::FnDef(..) | ty::FnPtr(_) => { self.consume_expr(callee); } @@ -658,7 +658,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // Select just those fields of the `with` // expression that will actually be used - match with_cmt.ty.sty { + match with_cmt.ty.kind { ty::Adt(adt, substs) if adt.is_struct() => { // Consume those fields of the with expression that are needed. for (f_index, with_field) in adt.non_enum_variant().fields.iter().enumerate() { @@ -867,7 +867,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { // It is also a borrow or copy/move of the value being matched. match bm { ty::BindByReference(m) => { - if let ty::Ref(r, _, _) = pat_ty.sty { + if let ty::Ref(r, _, _) = pat_ty.kind { let bk = ty::BorrowKind::from_mutbl(m); delegate.borrow(pat.hir_id, pat.span, &cmt_pat, r, bk, RefBinding); } diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 1cc96c549e724..73a2e7dff6b15 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -37,7 +37,7 @@ struct ExprVisitor<'tcx> { /// If the type is `Option`, it will return `T`, otherwise /// the type itself. Works on most `Option`-like types. fn unpack_option_like<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - let (def, substs) = match ty.sty { + let (def, substs) = match ty.kind { ty::Adt(def, substs) => (def, substs), _ => return ty }; @@ -83,7 +83,7 @@ impl ExprVisitor<'tcx> { // Special-case transmutting from `typeof(function)` and // `Option` to present a clearer error. let from = unpack_option_like(self.tcx.global_tcx(), from); - if let (&ty::FnDef(..), SizeSkeleton::Known(size_to)) = (&from.sty, sk_to) { + if let (&ty::FnDef(..), SizeSkeleton::Known(size_to)) = (&from.kind, sk_to) { if size_to == Pointer.size(&self.tcx) { struct_span_err!(self.tcx.sess, span, E0591, "can't transmute zero-sized type") diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 73ca981bbe868..e0149a3b9de55 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -738,7 +738,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { LocalDefId::from_def_id(closure_expr_def_id), ); let ty = self.node_ty(fn_hir_id)?; - let kind = match ty.sty { + let kind = match ty.kind { ty::Generator(..) => ty::ClosureKind::FnOnce, ty::Closure(closure_def_id, closure_substs) => { match self.infcx { @@ -900,7 +900,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { debug!("cat_rvalue_node: promotable = {:?}", promotable); // Always promote `[T; 0]` (even when e.g., borrowed mutably). - let promotable = match expr_ty.sty { + let promotable = match expr_ty.kind { ty::Array(_, len) if len.try_eval_usize(self.tcx, self.param_env) == Some(0) => true, _ => promotable, }; @@ -974,7 +974,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { let place_ty = self.expr_ty(expr)?; let base_ty = self.expr_ty_adjusted(base)?; - let (region, mutbl) = match base_ty.sty { + let (region, mutbl) = match base_ty.kind { ty::Ref(region, _, mutbl) => (region, mutbl), _ => span_bug!(expr.span, "cat_overloaded_place: base is not a reference") }; @@ -1004,7 +1004,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { } }; - let ptr = match base_cmt.ty.sty { + let ptr = match base_cmt.ty.kind { ty::Adt(def, ..) if def.is_box() => Unique, ty::RawPtr(ref mt) => UnsafePtr(mt.mutbl), ty::Ref(r, _, mutbl) => { @@ -1230,7 +1230,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), _) | Res::SelfCtor(..) => { let ty = self.pat_ty_unadjusted(&pat)?; - match ty.sty { + match ty.kind { ty::Adt(adt_def, _) => { (cmt, adt_def.non_enum_variant().fields.len()) } @@ -1303,7 +1303,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { PatKind::Tuple(ref subpats, ddpos) => { // (p1, ..., pN) let ty = self.pat_ty_unadjusted(&pat)?; - let expected_len = match ty.sty { + let expected_len = match ty.kind { ty::Tuple(ref tys) => tys.len(), _ => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty), }; diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index d776809839743..26f718e858da8 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -34,7 +34,7 @@ impl<'tcx> PlaceTy<'tcx> { /// /// Note that the resulting type has not been normalized. pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: &Field) -> Ty<'tcx> { - let answer = match self.ty.sty { + let answer = match self.ty.kind { ty::Adt(adt_def, substs) => { let variant_def = match self.variant_index { None => adt_def.non_enum_variant(), @@ -89,7 +89,7 @@ impl<'tcx> PlaceTy<'tcx> { ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } => PlaceTy::from_ty(self.ty.builtin_index().unwrap()), ProjectionElem::Subslice { from, to } => { - PlaceTy::from_ty(match self.ty.sty { + PlaceTy::from_ty(match self.ty.kind { ty::Array(inner, size) => { let size = size.eval_usize(tcx, param_env); let len = size - (from as u64) - (to as u64); @@ -195,7 +195,7 @@ impl<'tcx> Rvalue<'tcx> { } Rvalue::Discriminant(ref place) => { let ty = place.ty(local_decls, tcx).ty; - match ty.sty { + match ty.kind { ty::Adt(adt_def, _) => adt_def.repr.discr_type().to_ty(tcx), ty::Generator(_, substs, _) => substs.discr_ty(tcx), _ => { diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index d89cf8eb3e843..6c0ea128df892 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -601,7 +601,7 @@ impl AutoTraitFinder<'tcx> { } pub fn is_of_param(&self, ty: Ty<'_>) -> bool { - return match ty.sty { + return match ty.kind { ty::Param(_) => true, ty::Projection(p) => self.is_of_param(p.self_ty()), _ => false, @@ -609,7 +609,7 @@ impl AutoTraitFinder<'tcx> { } fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'_>) -> bool { - match p.ty().skip_binder().sty { + match p.ty().skip_binder().kind { ty::Projection(proj) if proj == p.skip_binder().projection_ty => { true }, diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index ee318b127ae66..039973d80dbf1 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -383,7 +383,7 @@ fn orphan_check_trait_ref<'tcx>( if ty_is_local(tcx, input_ty, in_crate) { debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty); return Ok(()); - } else if let ty::Param(_) = input_ty.sty { + } else if let ty::Param(_) = input_ty.kind { debug!("orphan_check_trait_ref: uncovered ty: `{:?}`", input_ty); return Err(OrphanCheckErr::UncoveredTy(input_ty)) } @@ -444,7 +444,7 @@ fn uncovered_tys<'tcx>(tcx: TyCtxt<'_>, ty: Ty<'tcx>, in_crate: InCrate) -> Vec< } fn is_possibly_remote_type(ty: Ty<'_>, _in_crate: InCrate) -> bool { - match ty.sty { + match ty.kind { ty::Projection(..) | ty::Param(..) => true, _ => false, } @@ -456,7 +456,7 @@ fn ty_is_local(tcx: TyCtxt<'_>, ty: Ty<'_>, in_crate: InCrate) -> bool { } fn fundamental_ty(ty: Ty<'_>) -> bool { - match ty.sty { + match ty.kind { ty::Ref(..) => true, ty::Adt(def, _) => def.is_fundamental(), _ => false @@ -475,7 +475,7 @@ fn def_id_is_local(def_id: DefId, in_crate: InCrate) -> bool { fn ty_is_local_constructor(tcx: TyCtxt<'_>, ty: Ty<'_>, in_crate: InCrate) -> bool { debug!("ty_is_local_constructor({:?})", ty); - match ty.sty { + match ty.kind { ty::Bool | ty::Char | ty::Int(..) | diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 08fea75739978..16c808edb6ef4 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -258,7 +258,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// returns the fuzzy category of a given type, or None /// if the type can be equated to any type. fn type_category(t: Ty<'_>) -> Option { - match t.sty { + match t.kind { ty::Bool => Some(0), ty::Char => Some(1), ty::Str => Some(2), @@ -288,7 +288,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } match (type_category(a), type_category(b)) { - (Some(cat_a), Some(cat_b)) => match (&a.sty, &b.sty) { + (Some(cat_a), Some(cat_b)) => match (&a.kind, &b.kind) { (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b, _ => cat_a == cat_b }, @@ -419,7 +419,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { flags.push((sym::_Self, Some("{integral}".to_owned()))); } - if let ty::Array(aty, len) = self_ty.sty { + if let ty::Array(aty, len) = self_ty.kind { flags.push((sym::_Self, Some("[]".to_owned()))); flags.push((sym::_Self, Some(format!("[{}]", aty)))); if let Some(def) = aty.ty_adt_def() { @@ -876,7 +876,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let found_trait_ty = found_trait_ref.self_ty(); - let found_did = match found_trait_ty.sty { + let found_did = match found_trait_ty.kind { ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did), ty::Adt(def, _) => Some(def.did), _ => None, @@ -886,13 +886,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.hir().span_if_local(did) ).map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def - let found = match found_trait_ref.skip_binder().substs.type_at(1).sty { + let found = match found_trait_ref.skip_binder().substs.type_at(1).kind { ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()], _ => vec![ArgKind::empty()], }; let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1); - let expected = match expected_ty.sty { + let expected = match expected_ty.kind { ty::Tuple(ref tys) => tys.iter() .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span))).collect(), _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())], @@ -979,7 +979,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { points_at_arg: bool, ) { let self_ty = trait_ref.self_ty(); - match self_ty.sty { + match self_ty.kind { ty::FnDef(def_id, _) => { // We tried to apply the bound to an `fn`. Check whether calling it would evaluate // to a type that *would* satisfy the trait binding. If it would, suggest calling @@ -1066,7 +1066,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let mut trait_type = trait_ref.self_ty(); for refs_remaining in 0..refs_number { - if let ty::Ref(_, t_type, _) = trait_type.sty { + if let ty::Ref(_, t_type, _) = trait_type.kind { trait_type = t_type; let substs = self.tcx.mk_substs_trait(trait_type, &[]); @@ -1340,7 +1340,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ) -> DiagnosticBuilder<'tcx> { fn build_fn_sig_string<'tcx>(tcx: TyCtxt<'tcx>, trait_ref: &ty::TraitRef<'tcx>) -> String { let inputs = trait_ref.substs.type_at(1); - let sig = if let ty::Tuple(inputs) = inputs.sty { + let sig = if let ty::Tuple(inputs) = inputs.kind { tcx.mk_fn_sig( inputs.iter().map(|k| k.expect_ty()), tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })), @@ -1564,7 +1564,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.infcx.tcx } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - if let ty::Param(ty::ParamTy {name, .. }) = ty.sty { + if let ty::Param(ty::ParamTy {name, .. }) = ty.kind { let infcx = self.infcx; self.var_map.entry(ty).or_insert_with(|| infcx.next_ty_var( @@ -1834,7 +1834,7 @@ impl ArgKind { /// Creates an `ArgKind` from the expected type of an /// argument. It has no name (`_`) and an optional source span. pub fn from_expected_ty(t: Ty<'_>, span: Option) -> ArgKind { - match t.sty { + match t.kind { ty::Tuple(ref tys) => ArgKind::Tuple( span, tys.iter() diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 6c421e9df6800..0a190af1f986d 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -548,7 +548,7 @@ fn trait_ref_type_vars<'a, 'tcx>( .map(|t| selcx.infcx().resolve_vars_if_possible(&t)) .filter(|t| t.has_infer_types()) .flat_map(|t| t.walk()) - .filter(|t| match t.sty { ty::Infer(_) => true, _ => false }) + .filter(|t| match t.kind { ty::Infer(_) => true, _ => false }) .collect() } diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index a7990c4af69fd..e0ef179911b6c 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -677,7 +677,7 @@ impl<'tcx> TyCtxt<'tcx> { let mut error = false; let self_ty = self.types.self_param; ty.maybe_walk(|ty| { - match ty.sty { + match ty.kind { ty::Param(_) => { if ty == self_ty { error = true; diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 87a23f655a8f3..57077bcdffa72 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -337,7 +337,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { // should occur eventually). let ty = ty.super_fold_with(self); - match ty.sty { + match ty.kind { ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { // (*) // Only normalize `impl Trait` after type-checking, usually in codegen. match self.param_env.reveal { @@ -921,7 +921,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>( let tcx = selcx.tcx(); // Check whether the self-type is itself a projection. - let (def_id, substs) = match obligation_trait_ref.self_ty().sty { + let (def_id, substs) = match obligation_trait_ref.self_ty().kind { ty::Projection(ref data) => { (data.trait_ref(tcx).def_id, data.substs) } @@ -1199,7 +1199,7 @@ fn confirm_object_candidate<'cx, 'tcx>( let object_ty = selcx.infcx().shallow_resolve(self_ty); debug!("confirm_object_candidate(object_ty={:?})", object_ty); - let data = match object_ty.sty { + let data = match object_ty.kind { ty::Dynamic(ref data, ..) => data, _ => { span_bug!( diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index 46403a38c99bd..673cae1ca0309 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -186,7 +186,7 @@ impl_stable_hash_for!(struct DtorckConstraint<'tcx> { /// Note also that `needs_drop` requires a "global" type (i.e., one /// with erased regions), but this function does not. pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { - match ty.sty { + match ty.kind { // None of these types have a destructor and hence they do not // require anything in particular to outlive the dtor's // execution. diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index c31ff3ab1b55d..b334e6dd8f84e 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -88,7 +88,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { let ty = ty.super_fold_with(self); - match ty.sty { + match ty.kind { ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { // (*) // Only normalize `impl Trait` after type-checking, usually in codegen. diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 386a5677f5f17..87191a4b4558d 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1785,7 +1785,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // before we go into the whole placeholder thing, just // quickly check if the self-type is a projection at all. - match obligation.predicate.skip_binder().trait_ref.self_ty().sty { + match obligation.predicate.skip_binder().trait_ref.self_ty().kind { ty::Projection(_) | ty::Opaque(..) => {} ty::Infer(ty::TyVar(_)) => { span_bug!( @@ -1823,7 +1823,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { placeholder_trait_predicate, ); - let (def_id, substs) = match placeholder_trait_predicate.trait_ref.self_ty().sty { + let (def_id, substs) = match placeholder_trait_predicate.trait_ref.self_ty().kind { ty::Projection(ref data) => (data.trait_ref(self.tcx()).def_id, data.substs), ty::Opaque(def_id, substs) => (def_id, substs), _ => { @@ -1971,7 +1971,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // touch bound regions, they just capture the in-scope // type/region parameters. let self_ty = *obligation.self_ty().skip_binder(); - match self_ty.sty { + match self_ty.kind { ty::Generator(..) => { debug!( "assemble_generator_candidates: self_ty={:?} obligation={:?}", @@ -2014,7 +2014,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Okay to skip binder because the substs on closure types never // touch bound regions, they just capture the in-scope // type/region parameters - match obligation.self_ty().skip_binder().sty { + match obligation.self_ty().skip_binder().kind { ty::Closure(closure_def_id, closure_substs) => { debug!( "assemble_unboxed_candidates: kind={:?} obligation={:?}", @@ -2063,7 +2063,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Okay to skip binder because what we are inspecting doesn't involve bound regions let self_ty = *obligation.self_ty().skip_binder(); - match self_ty.sty { + match self_ty.kind { ty::Infer(ty::TyVar(_)) => { debug!("assemble_fn_pointer_candidates: ambiguous self-type"); candidates.ambiguous = true; // could wind up being a fn() type @@ -2125,7 +2125,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let def_id = obligation.predicate.def_id(); if self.tcx().trait_is_auto(def_id) { - match self_ty.sty { + match self_ty.kind { ty::Dynamic(..) => { // For object types, we don't know what the closed // over types are. This means we conservatively @@ -2198,7 +2198,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // self-ty here doesn't escape this probe, so just erase // any LBR. let self_ty = self.tcx().erase_late_bound_regions(&obligation.self_ty()); - let poly_trait_ref = match self_ty.sty { + let poly_trait_ref = match self_ty.kind { ty::Dynamic(ref data, ..) => { if data.auto_traits() .any(|did| did == obligation.predicate.def_id()) @@ -2294,7 +2294,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { source, target ); - let may_apply = match (&source.sty, &target.sty) { + let may_apply = match (&source.kind, &target.kind) { // Trait+Kx+'a -> Trait+Ky+'b (upcasts). (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => { // Upcasts permit two things: @@ -2532,7 +2532,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let self_ty = self.infcx .shallow_resolve(obligation.predicate.skip_binder().self_ty()); - match self_ty.sty { + match self_ty.kind { ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) | ty::Uint(_) @@ -2598,7 +2598,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { use self::BuiltinImplConditions::{Ambiguous, None, Where}; - match self_ty.sty { + match self_ty.kind { ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) | ty::FnDef(..) @@ -2680,7 +2680,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// Zed where enum Zed { A(T), B(u32) } -> [i32, u32] /// ``` fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec> { - match t.sty { + match t.kind { ty::Uint(_) | ty::Int(_) | ty::Bool @@ -3118,7 +3118,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // results. let self_ty = self.infcx .shallow_resolve(*obligation.self_ty().skip_binder()); - let poly_trait_ref = match self_ty.sty { + let poly_trait_ref = match self_ty.kind { ty::Dynamic(ref data, ..) => data.principal().unwrap_or_else(|| { span_bug!(obligation.cause.span, "object candidate with no principal") @@ -3252,7 +3252,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // touch bound regions, they just capture the in-scope // type/region parameters. let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); - let (generator_def_id, substs) = match self_ty.sty { + let (generator_def_id, substs) = match self_ty.kind { ty::Generator(id, substs, _) => (id, substs), _ => bug!("closure candidate for non-closure {:?}", obligation), }; @@ -3309,7 +3309,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // touch bound regions, they just capture the in-scope // type/region parameters. let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); - let (closure_def_id, substs) = match self_ty.sty { + let (closure_def_id, substs) = match self_ty.kind { ty::Closure(id, substs) => (id, substs), _ => bug!("closure candidate for non-closure {:?}", obligation), }; @@ -3418,7 +3418,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); let mut nested = vec![]; - match (&source.sty, &target.sty) { + match (&source.kind, &target.kind) { // Trait+Kx+'a -> Trait+Ky+'b (upcasts). (&ty::Dynamic(ref data_a, r_a), &ty::Dynamic(ref data_b, r_b)) => { // See assemble_candidates_for_unsizing for more info. @@ -3550,7 +3550,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let mut ty_params = GrowableBitSet::new_empty(); let mut found = false; for ty in field.walk() { - if let ty::Param(p) = ty.sty { + if let ty::Param(p) = ty.kind { ty_params.insert(p.index as usize); found = true; } diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index c0d8230999dd8..dab62a6bcb5b1 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -312,7 +312,7 @@ impl<'tcx> TypeVisitor<'tcx> for BoundNamesCollector { } fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { - match t.sty { + match t.kind { ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => { self.types.insert( bound_ty.var.as_u32(), diff --git a/src/librustc/ty/_match.rs b/src/librustc/ty/_match.rs index f800a70e0becf..a0d22789dae35 100644 --- a/src/librustc/ty/_match.rs +++ b/src/librustc/ty/_match.rs @@ -59,7 +59,7 @@ impl TypeRelation<'tcx> for Match<'tcx> { a, b); if a == b { return Ok(a); } - match (&a.sty, &b.sty) { + match (&a.kind, &b.kind) { (_, &ty::Infer(ty::FreshTy(_))) | (_, &ty::Infer(ty::FreshIntTy(_))) | (_, &ty::Infer(ty::FreshFloatTy(_))) => { diff --git a/src/librustc/ty/cast.rs b/src/librustc/ty/cast.rs index 7ea5c73c5b749..bc12412312deb 100644 --- a/src/librustc/ty/cast.rs +++ b/src/librustc/ty/cast.rs @@ -52,7 +52,7 @@ impl<'tcx> CastTy<'tcx> { /// Returns `Some` for integral/pointer casts. /// casts like unsizing casts will return `None` pub fn from_ty(t: Ty<'tcx>) -> Option> { - match t.sty { + match t.kind { ty::Bool => Some(CastTy::Int(IntTy::Bool)), ty::Char => Some(CastTy::Int(IntTy::Char)), ty::Int(_) => Some(CastTy::Int(IntTy::I)), diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs index 1aa21501129c8..bd4913c88fd1f 100644 --- a/src/librustc/ty/codec.rs +++ b/src/librustc/ty/codec.rs @@ -31,7 +31,7 @@ pub trait EncodableWithShorthand: Clone + Eq + Hash { impl<'tcx> EncodableWithShorthand for Ty<'tcx> { type Variant = ty::TyKind<'tcx>; fn variant(&self) -> &Self::Variant { - &self.sty + &self.kind } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index c03dbb2b1ed0e..371ce885ce2ea 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -138,7 +138,7 @@ impl<'tcx> CtxtInterners<'tcx> { let flags = super::flags::FlagComputation::for_sty(&st); let ty_struct = TyS { - sty: st, + kind: st, flags: flags.flags, outer_exclusive_binder: flags.outer_exclusive_binder, }; @@ -828,7 +828,7 @@ impl CanonicalUserType<'tcx> { user_substs.substs.iter().zip(BoundVar::new(0)..).all(|(kind, cvar)| { match kind.unpack() { - UnpackedKind::Type(ty) => match ty.sty { + UnpackedKind::Type(ty) => match ty.kind { ty::Bound(debruijn, b) => { // We only allow a `ty::INNERMOST` index in substitutions. assert_eq!(debruijn, ty::INNERMOST); @@ -1565,7 +1565,7 @@ impl<'tcx> TyCtxt<'tcx> { } let ret_ty = self.type_of(scope_def_id); - match ret_ty.sty { + match ret_ty.kind { ty::FnDef(_, _) => { let sig = ret_ty.fn_sig(*self); let output = self.erase_late_bound_regions(&sig.output()); @@ -2011,7 +2011,7 @@ macro_rules! sty_debug_print { let shards = tcx.interners.type_.lock_shards(); let types = shards.iter().flat_map(|shard| shard.keys()); for &Interned(t) in types { - let variant = match t.sty { + let variant = match t.kind { ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) | ty::Float(..) | ty::Str | ty::Never => continue, ty::Error => /* unimportant */ continue, @@ -2083,7 +2083,7 @@ impl<'tcx, T: 'tcx+?Sized> Copy for Interned<'tcx, T> {} // N.B., an `Interned` compares and hashes as a sty. impl<'tcx> PartialEq for Interned<'tcx, TyS<'tcx>> { fn eq(&self, other: &Interned<'tcx, TyS<'tcx>>) -> bool { - self.0.sty == other.0.sty + self.0.kind == other.0.kind } } @@ -2091,14 +2091,14 @@ impl<'tcx> Eq for Interned<'tcx, TyS<'tcx>> {} impl<'tcx> Hash for Interned<'tcx, TyS<'tcx>> { fn hash(&self, s: &mut H) { - self.0.sty.hash(s) + self.0.kind.hash(s) } } #[allow(rustc::usage_of_ty_tykind)] impl<'tcx> Borrow> for Interned<'tcx, TyS<'tcx>> { fn borrow<'a>(&'a self) -> &'a TyKind<'tcx> { - &self.0.sty + &self.0.kind } } @@ -2292,7 +2292,7 @@ impl<'tcx> TyCtxt<'tcx> { /// It cannot convert a closure that requires unsafe. pub fn coerce_closure_fn_ty(self, sig: PolyFnSig<'tcx>, unsafety: hir::Unsafety) -> Ty<'tcx> { let converted_sig = sig.map_bound(|s| { - let params_iter = match s.inputs()[0].sty { + let params_iter = match s.inputs()[0].kind { ty::Tuple(params) => { params.into_iter().map(|k| k.expect_ty()) } diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 125c48f5f31d7..8b8708844979a 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -185,7 +185,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { impl<'tcx> ty::TyS<'tcx> { pub fn sort_string(&self, tcx: TyCtxt<'_>) -> Cow<'static, str> { - match self.sty { + match self.kind { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => self.to_string().into(), ty::Tuple(ref tys) if tys.is_empty() => self.to_string().into(), @@ -275,7 +275,7 @@ impl<'tcx> TyCtxt<'tcx> { `.await`ing on both of them"); } } - match (&values.expected.sty, &values.found.sty) { + match (&values.expected.kind, &values.found.kind) { (ty::Float(_), ty::Infer(ty::IntVar(_))) => if let Ok( // Issue #53280 snippet, ) = self.sess.source_map().span_to_snippet(sp) { diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index ee0d33dbe345c..7d6ae3f815af1 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -60,7 +60,7 @@ pub fn simplify_type( ty: Ty<'_>, can_simplify_params: bool, ) -> Option { - match ty.sty { + match ty.kind { ty::Bool => Some(BoolSimplifiedType), ty::Char => Some(CharSimplifiedType), ty::Int(int_type) => Some(IntSimplifiedType(int_type)), diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 1e08ae45951d1..f6a5092d30d40 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -472,7 +472,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for BoundVarReplacer<'a, 'tcx> { } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - match t.sty { + match t.kind { ty::Bound(debruijn, bound_ty) => { if debruijn == self.current_index { let fld_t = &mut self.fld_t; @@ -776,7 +776,7 @@ impl TypeFolder<'tcx> for Shifter<'tcx> { } fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { - match ty.sty { + match ty.kind { ty::Bound(debruijn, bound_ty) => { if self.amount == 0 || debruijn < self.current_index { ty @@ -985,7 +985,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { // ignore the inputs to a projection, as they may not appear // in the normalized form if self.just_constrained { - match t.sty { + match t.kind { ty::Projection(..) | ty::Opaque(..) => { return false; } _ => { } } diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index 1a0e351733877..bc0cf4deaa47b 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -181,7 +181,7 @@ impl<'tcx> FieldDef { impl<'tcx> TyS<'tcx> { /// Calculates the forest of `DefId`s from which this type is visibly uninhabited. fn uninhabited_from(&self, tcx: TyCtxt<'tcx>) -> DefIdForest { - match self.sty { + match self.kind { Adt(def, substs) => def.uninhabited_from(tcx, substs), Never => DefIdForest::full(tcx), diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index a26fa72f33041..ecb512b0cd1a2 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -54,7 +54,7 @@ impl<'tcx> Instance<'tcx> { fn fn_sig_noadjust(&self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> { let ty = self.ty(tcx); - match ty.sty { + match ty.kind { ty::FnDef(..) | // Shims currently have type FnPtr. Not sure this should remain. ty::FnPtr(_) => ty.fn_sig(tcx), @@ -255,7 +255,7 @@ impl<'tcx> Instance<'tcx> { &ty, ); - let def = match item_type.sty { + let def = match item_type.kind { ty::FnDef(..) if { let f = item_type.fn_sig(tcx); f.abi() == Abi::RustIntrinsic || diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index e52feea1624c1..790b0c5cb48f4 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -520,7 +520,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }; debug_assert!(!ty.has_infer_types()); - Ok(match ty.sty { + Ok(match ty.kind { // Basic scalars. ty::Bool => { tcx.intern_layout(LayoutDetails::scalar(self, Scalar { @@ -573,7 +573,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env); - let metadata = match unsized_part.sty { + let metadata = match unsized_part.kind { ty::Foreign(..) => { return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr))); } @@ -1618,7 +1618,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { variants); }; - let adt_def = match layout.ty.sty { + let adt_def = match layout.ty.kind { ty::Adt(ref adt_def, _) => { debug!("print-type-size t: `{:?}` process adt", layout.ty); adt_def @@ -1759,12 +1759,12 @@ impl<'tcx> SizeSkeleton<'tcx> { Err(err) => err }; - match ty.sty { + match ty.kind { ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => { let non_zero = !ty.is_unsafe_ptr(); let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env); - match tail.sty { + match tail.kind { ty::Param(_) | ty::Projection(_) => { debug_assert!(tail.has_param_types()); Ok(SizeSkeleton::Pointer { @@ -2040,7 +2040,7 @@ where assert_eq!(layout.variants, Variants::Single { index }); } - let fields = match this.ty.sty { + let fields = match this.ty.kind { ty::Adt(def, _) => def.variants[variant_index].fields.len(), _ => bug!() }; @@ -2078,7 +2078,7 @@ where })) }; - cx.layout_of(match this.ty.sty { + cx.layout_of(match this.ty.kind { ty::Bool | ty::Char | ty::Int(_) | @@ -2115,7 +2115,7 @@ where })); } - match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).sty { + match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind { ty::Slice(_) | ty::Str => tcx.types.usize, ty::Dynamic(_, _) => { @@ -2202,7 +2202,7 @@ where cx: &C, offset: Size, ) -> Option { - match this.ty.sty { + match this.ty.kind { ty::RawPtr(mt) if offset.bytes() == 0 => { cx.layout_of(mt.ty).to_result().ok() .map(|layout| PointeeInfo { @@ -2309,7 +2309,7 @@ where // FIXME(eddyb) This should be for `ptr::Unique`, not `Box`. if let Some(ref mut pointee) = result { - if let ty::Adt(def, _) = this.ty.sty { + if let ty::Adt(def, _) = this.ty.kind { if def.is_box() && offset.bytes() == 0 { pointee.safe = Some(PointerKind::UniqueOwned); } @@ -2641,7 +2641,7 @@ where let extra_args = if sig.abi == RustCall { assert!(!sig.c_variadic && extra_args.is_empty()); - match sig.inputs().last().unwrap().sty { + match sig.inputs().last().unwrap().kind { ty::Tuple(tupled_arguments) => { inputs = &sig.inputs()[0..sig.inputs().len() - 1]; tupled_arguments.iter().map(|k| k.expect_ty()).collect() @@ -2753,7 +2753,7 @@ where Some(did) => did, None => bug!("`va_list` lang item required for C-variadic functions"), }; - match ty.sty { + match ty.kind { ty::Adt(def, _) if def.did == va_list_did => { // This is the "spoofed" `VaListImpl`. Set the arguments mode // so that it will be ignored. diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index ef8bdfb583edf..0c1b2a23d442d 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -479,7 +479,7 @@ bitflags! { #[allow(rustc::usage_of_ty_tykind)] pub struct TyS<'tcx> { - pub sty: TyKind<'tcx>, + pub kind: TyKind<'tcx>, pub flags: TypeFlags, /// This is a kind of confusing thing: it stores the smallest @@ -508,13 +508,13 @@ static_assert_size!(TyS<'_>, 32); impl<'tcx> Ord for TyS<'tcx> { fn cmp(&self, other: &TyS<'tcx>) -> Ordering { - self.sty.cmp(&other.sty) + self.kind.cmp(&other.kind) } } impl<'tcx> PartialOrd for TyS<'tcx> { fn partial_cmp(&self, other: &TyS<'tcx>) -> Option { - Some(self.sty.cmp(&other.sty)) + Some(self.kind.cmp(&other.kind)) } } @@ -534,7 +534,7 @@ impl<'tcx> Hash for TyS<'tcx> { impl<'tcx> TyS<'tcx> { pub fn is_primitive_ty(&self) -> bool { - match self.sty { + match self.kind { Bool | Char | Int(_) | @@ -550,7 +550,7 @@ impl<'tcx> TyS<'tcx> { } pub fn is_suggestable(&self) -> bool { - match self.sty { + match self.kind { Opaque(..) | FnDef(..) | FnPtr(..) | @@ -568,16 +568,16 @@ impl<'a, 'tcx> HashStable> for ty::TyS<'tcx> { hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let ty::TyS { - ref sty, + ref kind, // The other fields just provide fast access to information that is - // also contained in `sty`, so no need to hash them. + // also contained in `kind`, so no need to hash them. flags: _, outer_exclusive_binder: _, } = *self; - sty.hash_stable(hcx, hasher); + kind.hash_stable(hcx, hasher); } } @@ -2494,7 +2494,7 @@ impl<'tcx> AdtDef { } fn sized_constraint_for_ty(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Vec> { - let result = match ty.sty { + let result = match ty.kind { Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..) | FnPtr(_) | Array(..) | Closure(..) | Generator(..) | Never => { @@ -3339,7 +3339,7 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { } let self_ty = trait_ref.self_ty(); - let self_ty_matches = match self_ty.sty { + let self_ty_matches = match self_ty.kind { ty::Dynamic(ref data, ty::ReStatic) => data.principal().is_none(), _ => false }; diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index 7d1403d1e9662..9a2e30f7f45ed 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -60,7 +60,7 @@ impl<'tcx> TyCtxt<'tcx> { // with `collect()` because of the need to sometimes skip subtrees // in the `subtys` iterator (e.g., when encountering a // projection). - match ty.sty { + match ty.kind { ty::Closure(def_id, ref substs) => { for upvar_ty in substs.upvar_tys(def_id, *self) { self.compute_components(upvar_ty, out); diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index 50789bf6213b6..727397d7a29ab 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -266,7 +266,7 @@ pub trait Printer<'tcx>: Sized { /// type. It's just a heuristic so it makes some questionable /// decisions and we may want to adjust it later. pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { - match ty.sty { + match ty.kind { ty::Adt(adt_def, _) => Some(adt_def.did), ty::Dynamic(data, ..) => data.principal_def_id(), diff --git a/src/librustc/ty/print/obsolete.rs b/src/librustc/ty/print/obsolete.rs index b68e6a744872f..d7d43b8203f6f 100644 --- a/src/librustc/ty/print/obsolete.rs +++ b/src/librustc/ty/print/obsolete.rs @@ -34,7 +34,7 @@ impl DefPathBasedNames<'tcx> { // When being used for codegen purposes, `debug` should be set to `false` // in order to catch unexpected types that should never end up in a type name. pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String, debug: bool) { - match t.sty { + match t.kind { ty::Bool => output.push_str("bool"), ty::Char => output.push_str("char"), ty::Str => output.push_str("str"), diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index d99580116e4ae..a38a00ff5b759 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -414,7 +414,7 @@ pub trait PrettyPrinter<'tcx>: // Inherent impls. Try to print `Foo::bar` for an inherent // impl on `Foo`, but fallback to `::bar` if self-type is // anything other than a simple path. - match self_ty.sty { + match self_ty.kind { ty::Adt(..) | ty::Foreign(_) | ty::Bool | ty::Char | ty::Str | ty::Int(_) | ty::Uint(_) | ty::Float(_) => { @@ -463,7 +463,7 @@ pub trait PrettyPrinter<'tcx>: ) -> Result { define_scoped_cx!(self); - match ty.sty { + match ty.kind { ty::Bool => p!(write("bool")), ty::Char => p!(write("char")), ty::Int(t) => p!(write("{}", t.ty_to_string())), @@ -739,7 +739,7 @@ pub trait PrettyPrinter<'tcx>: // Special-case `Fn(...) -> ...` and resugar it. let fn_trait_kind = self.tcx().lang_items().fn_trait_kind(principal.def_id); if !self.tcx().sess.verbose() && fn_trait_kind.is_some() { - if let ty::Tuple(ref args) = principal.substs.type_at(0).sty { + if let ty::Tuple(ref args) = principal.substs.type_at(0).kind { let mut projections = predicates.projection_bounds(); if let (Some(proj), None) = (projections.next(), projections.next()) { let tys: Vec<_> = args.iter().map(|k| k.expect_ty()).collect(); @@ -856,7 +856,7 @@ pub trait PrettyPrinter<'tcx>: define_scoped_cx!(self); let u8 = self.tcx().types.u8; - if let ty::FnDef(did, substs) = ct.ty.sty { + if let ty::FnDef(did, substs) = ct.ty.kind { p!(print_value_path(did, substs)); return Ok(self); } @@ -887,7 +887,7 @@ pub trait PrettyPrinter<'tcx>: return Ok(self); } if let ConstValue::Scalar(Scalar::Raw { data, .. }) = ct.val { - match ct.ty.sty { + match ct.ty.kind { ty::Bool => { p!(write("{}", if data == 0 { "false" } else { "true" })); return Ok(self); @@ -935,8 +935,8 @@ pub trait PrettyPrinter<'tcx>: _ => {}, } } - if let ty::Ref(_, ref_ty, _) = ct.ty.sty { - let byte_str = match (ct.val, &ref_ty.sty) { + if let ty::Ref(_, ref_ty, _) = ct.ty.kind { + let byte_str = match (ct.val, &ref_ty.kind) { (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => { let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty()); Some(self.tcx() diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 565447dd7e1af..d6bd4eeb7367a 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -349,7 +349,7 @@ pub fn super_relate_tys>( ) -> RelateResult<'tcx, Ty<'tcx>> { let tcx = relation.tcx(); debug!("super_relate_tys: a={:?} b={:?}", a, b); - match (&a.sty, &b.sty) { + match (&a.kind, &b.kind) { (&ty::Infer(_), _) | (_, &ty::Infer(_)) => { diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index ec7cf1a13c596..72e1bd33c6a81 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -1023,7 +1023,7 @@ impl<'tcx> TypeFoldable<'tcx> for interpret::GlobalId<'tcx> { impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { fn super_fold_with>(&self, folder: &mut F) -> Self { - let sty = match self.sty { + let sty = match self.kind { ty::RawPtr(tm) => ty::RawPtr(tm.fold_with(folder)), ty::Array(typ, sz) => ty::Array(typ.fold_with(folder), sz.fold_with(folder)), ty::Slice(typ) => ty::Slice(typ.fold_with(folder)), @@ -1067,7 +1067,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::Foreign(..) => return self }; - if self.sty == sty { + if self.kind == sty { self } else { folder.tcx().mk_ty(sty) @@ -1079,7 +1079,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { } fn super_visit_with>(&self, visitor: &mut V) -> bool { - match self.sty { + match self.kind { ty::RawPtr(ref tm) => tm.visit_with(visitor), ty::Array(typ, sz) => typ.visit_with(visitor) || sz.visit_with(visitor), ty::Slice(typ) => typ.visit_with(visitor), diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index e73a51e6f78e5..e5eca7521353e 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -384,9 +384,9 @@ impl<'tcx> ClosureSubsts<'tcx> { /// If you have an inference context, use `infcx.closure_sig()`. pub fn closure_sig(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { let ty = self.closure_sig_ty(def_id, tcx); - match ty.sty { + match ty.kind { ty::FnPtr(sig) => sig, - _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty.sty), + _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty.kind), } } } @@ -1678,7 +1678,7 @@ impl RegionKind { impl<'tcx> TyS<'tcx> { #[inline] pub fn is_unit(&self) -> bool { - match self.sty { + match self.kind { Tuple(ref tys) => tys.is_empty(), _ => false, } @@ -1686,7 +1686,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_never(&self) -> bool { - match self.sty { + match self.kind { Never => true, _ => false, } @@ -1701,7 +1701,7 @@ impl<'tcx> TyS<'tcx> { pub fn conservative_is_privately_uninhabited(&self, tcx: TyCtxt<'tcx>) -> bool { // FIXME(varkor): we can make this less conversative by substituting concrete // type arguments. - match self.sty { + match self.kind { ty::Never => true, ty::Adt(def, _) if def.is_union() => { // For now, `union`s are never considered uninhabited. @@ -1741,7 +1741,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_primitive(&self) -> bool { - match self.sty { + match self.kind { Bool | Char | Int(_) | Uint(_) | Float(_) => true, _ => false, } @@ -1749,7 +1749,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_ty_var(&self) -> bool { - match self.sty { + match self.kind { Infer(TyVar(_)) => true, _ => false, } @@ -1757,7 +1757,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_ty_infer(&self) -> bool { - match self.sty { + match self.kind { Infer(_) => true, _ => false, } @@ -1765,7 +1765,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_phantom_data(&self) -> bool { - if let Adt(def, _) = self.sty { + if let Adt(def, _) = self.kind { def.is_phantom_data() } else { false @@ -1773,11 +1773,11 @@ impl<'tcx> TyS<'tcx> { } #[inline] - pub fn is_bool(&self) -> bool { self.sty == Bool } + pub fn is_bool(&self) -> bool { self.kind == Bool } #[inline] pub fn is_param(&self, index: u32) -> bool { - match self.sty { + match self.kind { ty::Param(ref data) => data.index == index, _ => false, } @@ -1785,8 +1785,8 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_slice(&self) -> bool { - match self.sty { - RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => match ty.sty { + match self.kind { + RawPtr(TypeAndMut { ty, .. }) | Ref(_, ty, _) => match ty.kind { Slice(_) | Str => true, _ => false, }, @@ -1796,14 +1796,14 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_simd(&self) -> bool { - match self.sty { + match self.kind { Adt(def, _) => def.repr.simd(), _ => false, } } pub fn sequence_element_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - match self.sty { + match self.kind { Array(ty, _) | Slice(ty) => ty, Str => tcx.mk_mach_uint(ast::UintTy::U8), _ => bug!("sequence_element_type called on non-sequence value: {}", self), @@ -1811,7 +1811,7 @@ impl<'tcx> TyS<'tcx> { } pub fn simd_type(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - match self.sty { + match self.kind { Adt(def, substs) => { def.non_enum_variant().fields[0].ty(tcx, substs) } @@ -1820,7 +1820,7 @@ impl<'tcx> TyS<'tcx> { } pub fn simd_size(&self, _cx: TyCtxt<'_>) -> usize { - match self.sty { + match self.kind { Adt(def, _) => def.non_enum_variant().fields.len(), _ => bug!("simd_size called on invalid type") } @@ -1828,7 +1828,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_region_ptr(&self) -> bool { - match self.sty { + match self.kind { Ref(..) => true, _ => false, } @@ -1836,7 +1836,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_mutable_ptr(&self) -> bool { - match self.sty { + match self.kind { RawPtr(TypeAndMut { mutbl: hir::Mutability::MutMutable, .. }) | Ref(_, _, hir::Mutability::MutMutable) => true, _ => false @@ -1845,7 +1845,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_unsafe_ptr(&self) -> bool { - match self.sty { + match self.kind { RawPtr(_) => return true, _ => return false, } @@ -1860,7 +1860,7 @@ impl<'tcx> TyS<'tcx> { /// Returns `true` if this type is an `Arc`. #[inline] pub fn is_arc(&self) -> bool { - match self.sty { + match self.kind { Adt(def, _) => def.is_arc(), _ => false, } @@ -1869,7 +1869,7 @@ impl<'tcx> TyS<'tcx> { /// Returns `true` if this type is an `Rc`. #[inline] pub fn is_rc(&self) -> bool { - match self.sty { + match self.kind { Adt(def, _) => def.is_rc(), _ => false, } @@ -1877,7 +1877,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_box(&self) -> bool { - match self.sty { + match self.kind { Adt(def, _) => def.is_box(), _ => false, } @@ -1885,7 +1885,7 @@ impl<'tcx> TyS<'tcx> { /// panics if called on any type other than `Box` pub fn boxed_ty(&self) -> Ty<'tcx> { - match self.sty { + match self.kind { Adt(def, substs) if def.is_box() => substs.type_at(0), _ => bug!("`boxed_ty` is called on non-box type {:?}", self), } @@ -1896,7 +1896,7 @@ impl<'tcx> TyS<'tcx> { /// contents are abstract to rustc.) #[inline] pub fn is_scalar(&self) -> bool { - match self.sty { + match self.kind { Bool | Char | Int(_) | Float(_) | Uint(_) | Infer(IntVar(_)) | Infer(FloatVar(_)) | FnDef(..) | FnPtr(_) | RawPtr(_) => true, @@ -1907,7 +1907,7 @@ impl<'tcx> TyS<'tcx> { /// Returns `true` if this type is a floating point type. #[inline] pub fn is_floating_point(&self) -> bool { - match self.sty { + match self.kind { Float(_) | Infer(FloatVar(_)) => true, _ => false, @@ -1916,7 +1916,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_trait(&self) -> bool { - match self.sty { + match self.kind { Dynamic(..) => true, _ => false, } @@ -1924,7 +1924,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_enum(&self) -> bool { - match self.sty { + match self.kind { Adt(adt_def, _) => { adt_def.is_enum() } @@ -1934,7 +1934,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_closure(&self) -> bool { - match self.sty { + match self.kind { Closure(..) => true, _ => false, } @@ -1942,7 +1942,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_generator(&self) -> bool { - match self.sty { + match self.kind { Generator(..) => true, _ => false, } @@ -1950,7 +1950,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_integral(&self) -> bool { - match self.sty { + match self.kind { Infer(IntVar(_)) | Int(_) | Uint(_) => true, _ => false } @@ -1958,7 +1958,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_fresh_ty(&self) -> bool { - match self.sty { + match self.kind { Infer(FreshTy(_)) => true, _ => false, } @@ -1966,7 +1966,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_fresh(&self) -> bool { - match self.sty { + match self.kind { Infer(FreshTy(_)) => true, Infer(FreshIntTy(_)) => true, Infer(FreshFloatTy(_)) => true, @@ -1976,7 +1976,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_char(&self) -> bool { - match self.sty { + match self.kind { Char => true, _ => false, } @@ -1989,7 +1989,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_signed(&self) -> bool { - match self.sty { + match self.kind { Int(_) => true, _ => false, } @@ -1997,7 +1997,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_ptr_sized_integral(&self) -> bool { - match self.sty { + match self.kind { Int(ast::IntTy::Isize) | Uint(ast::UintTy::Usize) => true, _ => false, } @@ -2005,7 +2005,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_machine(&self) -> bool { - match self.sty { + match self.kind { Int(..) | Uint(..) | Float(..) => true, _ => false, } @@ -2013,7 +2013,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn has_concrete_skeleton(&self) -> bool { - match self.sty { + match self.kind { Param(_) | Infer(_) | Error => false, _ => true, } @@ -2024,7 +2024,7 @@ impl<'tcx> TyS<'tcx> { /// The parameter `explicit` indicates if this is an *explicit* dereference. /// Some types -- notably unsafe ptrs -- can only be dereferenced explicitly. pub fn builtin_deref(&self, explicit: bool) -> Option> { - match self.sty { + match self.kind { Adt(def, _) if def.is_box() => { Some(TypeAndMut { ty: self.boxed_ty(), @@ -2039,14 +2039,14 @@ impl<'tcx> TyS<'tcx> { /// Returns the type of `ty[i]`. pub fn builtin_index(&self) -> Option> { - match self.sty { + match self.kind { Array(ty, _) | Slice(ty) => Some(ty), _ => None, } } pub fn fn_sig(&self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'tcx> { - match self.sty { + match self.kind { FnDef(def_id, substs) => { tcx.fn_sig(def_id).subst(tcx, substs) } @@ -2063,7 +2063,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_fn(&self) -> bool { - match self.sty { + match self.kind { FnDef(..) | FnPtr(_) => true, _ => false, } @@ -2071,7 +2071,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_fn_ptr(&self) -> bool { - match self.sty { + match self.kind { FnPtr(_) => true, _ => false, } @@ -2079,7 +2079,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_impl_trait(&self) -> bool { - match self.sty { + match self.kind { Opaque(..) => true, _ => false, } @@ -2087,7 +2087,7 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn ty_adt_def(&self) -> Option<&'tcx AdtDef> { - match self.sty { + match self.kind { Adt(adt, _) => Some(adt), _ => None, } @@ -2096,7 +2096,7 @@ impl<'tcx> TyS<'tcx> { /// Iterates over tuple fields. /// Panics when called on anything but a tuple. pub fn tuple_fields(&self) -> impl DoubleEndedIterator> { - match self.sty { + match self.kind { Tuple(substs) => substs.iter().map(|field| field.expect_ty()), _ => bug!("tuple_fields called on non-tuple"), } @@ -2106,7 +2106,7 @@ impl<'tcx> TyS<'tcx> { /// FIXME This requires the optimized MIR in the case of generators. #[inline] pub fn variant_range(&self, tcx: TyCtxt<'tcx>) -> Option> { - match self.sty { + match self.kind { TyKind::Adt(adt, _) => Some(adt.variant_range()), TyKind::Generator(def_id, substs, _) => Some(substs.variant_range(def_id, tcx)), _ => None, @@ -2122,7 +2122,7 @@ impl<'tcx> TyS<'tcx> { tcx: TyCtxt<'tcx>, variant_index: VariantIdx, ) -> Option> { - match self.sty { + match self.kind { TyKind::Adt(adt, _) => Some(adt.discriminant_for_variant(tcx, variant_index)), TyKind::Generator(def_id, substs, _) => Some(substs.discriminant_for_variant(def_id, tcx, variant_index)), @@ -2134,7 +2134,7 @@ impl<'tcx> TyS<'tcx> { /// types reachable from this type via `walk_tys`). This ignores late-bound /// regions binders. pub fn push_regions(&self, out: &mut SmallVec<[ty::Region<'tcx>; 4]>) { - match self.sty { + match self.kind { Ref(region, _, _) => { out.push(region); } @@ -2190,7 +2190,7 @@ impl<'tcx> TyS<'tcx> { /// inferred. Once upvar inference (in `src/librustc_typeck/check/upvar.rs`) /// is complete, that type variable will be unified. pub fn to_opt_closure_kind(&self) -> Option { - match self.sty { + match self.kind { Int(int_ty) => match int_ty { ast::IntTy::I8 => Some(ty::ClosureKind::Fn), ast::IntTy::I16 => Some(ty::ClosureKind::FnMut), @@ -2211,7 +2211,7 @@ impl<'tcx> TyS<'tcx> { /// Returning true means the type is known to be sized. Returning /// `false` means nothing -- could be sized, might not be. pub fn is_trivially_sized(&self, tcx: TyCtxt<'tcx>) -> bool { - match self.sty { + match self.kind { ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) | ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) | ty::FnDef(..) | ty::FnPtr(_) | ty::RawPtr(..) | diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index ea829da783e9b..b5debc179e923 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -501,7 +501,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> { } self.ty_stack_depth += 1; - let t1 = match t.sty { + let t1 = match t.kind { ty::Param(p) => { self.ty_for_param(p, t) } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 78d94df4fa03b..714ebf4c42ff8 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -33,7 +33,7 @@ pub struct Discr<'tcx> { impl<'tcx> fmt::Display for Discr<'tcx> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.ty.sty { + match self.ty.kind { ty::Int(ity) => { let size = ty::tls::with(|tcx| { Integer::from_attr(&tcx, SignedInt(ity)).size() @@ -54,7 +54,7 @@ impl<'tcx> Discr<'tcx> { self.checked_add(tcx, 1).0 } pub fn checked_add(self, tcx: TyCtxt<'tcx>, n: u128) -> (Self, bool) { - let (int, signed) = match self.ty.sty { + let (int, signed) = match self.ty.kind { Int(ity) => (Integer::from_attr(&tcx, SignedInt(ity)), true), Uint(uty) => (Integer::from_attr(&tcx, UnsignedInt(uty)), false), _ => bug!("non integer discriminant"), @@ -179,7 +179,7 @@ impl<'tcx> ty::ParamEnv<'tcx> { ) -> Result<(), CopyImplementationError<'tcx>> { // FIXME: (@jroesch) float this code up tcx.infer_ctxt().enter(|infcx| { - let (adt, substs) = match self_type.sty { + let (adt, substs) = match self_type.kind { // These types used to have a builtin impl. // Now libcore provides that impl. ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) | @@ -246,10 +246,10 @@ impl<'tcx> TyCtxt<'tcx> { impl<'tcx> TyCtxt<'tcx> { pub fn has_error_field(self, ty: Ty<'tcx>) -> bool { - if let ty::Adt(def, substs) = ty.sty { + if let ty::Adt(def, substs) = ty.kind { for field in def.all_fields() { let field_ty = field.ty(self, substs); - if let Error = field_ty.sty { + if let Error = field_ty.kind { return true; } } @@ -298,7 +298,7 @@ impl<'tcx> TyCtxt<'tcx> { -> Ty<'tcx> { loop { - match ty.sty { + match ty.kind { ty::Adt(def, substs) => { if !def.is_struct() { break; @@ -370,7 +370,7 @@ impl<'tcx> TyCtxt<'tcx> { { let (mut a, mut b) = (source, target); loop { - match (&a.sty, &b.sty) { + match (&a.kind, &b.kind) { (&Adt(a_def, a_substs), &Adt(b_def, b_substs)) if a_def == b_def && a_def.is_struct() => { if let Some(f) = a_def.non_enum_variant().fields.last() { @@ -544,12 +544,12 @@ impl<'tcx> TyCtxt<'tcx> { // , and then look up which of the impl substs refer to // parameters marked as pure. - let impl_substs = match self.type_of(impl_def_id).sty { + let impl_substs = match self.type_of(impl_def_id).kind { ty::Adt(def_, substs) if def_ == def => substs, _ => bug!() }; - let item_substs = match self.type_of(def.did).sty { + let item_substs = match self.type_of(def.did).kind { ty::Adt(def_, substs) if def_ == def => substs, _ => bug!() }; @@ -561,7 +561,7 @@ impl<'tcx> TyCtxt<'tcx> { !impl_generics.region_param(ebr, self).pure_wrt_drop } UnpackedKind::Type(&ty::TyS { - sty: ty::Param(ref pt), .. + kind: ty::Param(ref pt), .. }) => { !impl_generics.type_param(pt, self).pure_wrt_drop } @@ -733,7 +733,7 @@ impl<'tcx> TyCtxt<'tcx> { } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if let ty::Opaque(def_id, substs) = t.sty { + if let ty::Opaque(def_id, substs) = t.kind { self.expand_opaque_ty(def_id, substs).unwrap_or(t) } else { t.super_fold_with(self) @@ -811,7 +811,7 @@ impl<'tcx> ty::TyS<'tcx> { } pub fn same_type(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { - match (&a.sty, &b.sty) { + match (&a.kind, &b.kind) { (&Adt(did_a, substs_a), &Adt(did_b, substs_b)) => { if did_a != did_b { return false; @@ -846,7 +846,7 @@ impl<'tcx> ty::TyS<'tcx> { representable_cache: &mut FxHashMap, Representability>, ty: Ty<'tcx>, ) -> Representability { - match ty.sty { + match ty.kind { Tuple(..) => { // Find non representable fold_repr(ty.tuple_fields().map(|ty| { @@ -889,7 +889,7 @@ impl<'tcx> ty::TyS<'tcx> { } fn same_struct_or_enum<'tcx>(ty: Ty<'tcx>, def: &'tcx ty::AdtDef) -> bool { - match ty.sty { + match ty.kind { Adt(ty_def, _) => { ty_def == def } @@ -927,7 +927,7 @@ impl<'tcx> ty::TyS<'tcx> { representable_cache: &mut FxHashMap, Representability>, ty: Ty<'tcx>, ) -> Representability { - match ty.sty { + match ty.kind { Adt(def, _) => { { // Iterate through stack of previously seen types. @@ -1009,7 +1009,7 @@ impl<'tcx> ty::TyS<'tcx> { /// - `&'a *const &'b u8 -> *const &'b u8` pub fn peel_refs(&'tcx self) -> Ty<'tcx> { let mut ty = self; - while let Ref(_, inner_ty, _) = ty.sty { + while let Ref(_, inner_ty, _) = ty.kind { ty = inner_ty; } ty @@ -1067,7 +1067,7 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx> assert!(!ty.needs_infer()); - NeedsDrop(match ty.sty { + NeedsDrop(match ty.kind { // Fast-path for primitive types ty::Infer(ty::FreshIntTy(_)) | ty::Infer(ty::FreshFloatTy(_)) | ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Never | @@ -1170,7 +1170,7 @@ impl<'tcx> ExplicitSelf<'tcx> { { use self::ExplicitSelf::*; - match self_arg_ty.sty { + match self_arg_ty.kind { _ if is_self_ty(self_arg_ty) => ByValue, ty::Ref(region, ty, mutbl) if is_self_ty(ty) => { ByReference(region, mutbl) diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index 8c3110792a8b4..12f0d80cd0e1c 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -69,7 +69,7 @@ pub fn walk_shallow(ty: Ty<'_>) -> smallvec::IntoIter> { // natural order one would expect (basically, the order of the // types as they are written). fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { - match parent_ty.sty { + match parent_ty.kind { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Infer(_) | ty::Param(_) | ty::Never | ty::Error | ty::Placeholder(..) | ty::Bound(..) | ty::Foreign(..) => { diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index d6de217f79c29..020926e7c8de8 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -236,7 +236,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { let mut subtys = ty0.walk(); let param_env = self.param_env; while let Some(ty) = subtys.next() { - match ty.sty { + match ty.kind { ty::Bool | ty::Char | ty::Int(..) | @@ -407,7 +407,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // is satisfied to ensure termination.) ty::Infer(_) => { let ty = self.infcx.shallow_resolve(ty); - if let ty::Infer(_) = ty.sty { // not yet resolved... + if let ty::Infer(_) = ty.kind { // not yet resolved... if ty == ty0 { // ...this is the type we started from! no progress. return false; } diff --git a/src/librustc_ast_borrowck/borrowck/check_loans.rs b/src/librustc_ast_borrowck/borrowck/check_loans.rs index 3d824ee6ce1e8..fcede3eae976f 100644 --- a/src/librustc_ast_borrowck/borrowck/check_loans.rs +++ b/src/librustc_ast_borrowck/borrowck/check_loans.rs @@ -615,7 +615,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { self.check_if_assigned_path_is_moved(id, lp_base); } LpExtend(ref lp_base, _, LpInterior(_, InteriorField(_))) => { - match lp_base.to_type().sty { + match lp_base.to_type().kind { ty::Adt(def, _) if def.has_dtor(self.tcx()) => { // In the case where the owner implements drop, then // the path must be initialized to prevent a case of diff --git a/src/librustc_ast_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_ast_borrowck/borrowck/gather_loans/gather_moves.rs index 617161109b573..2239bf56bbed2 100644 --- a/src/librustc_ast_borrowck/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc_ast_borrowck/borrowck/gather_loans/gather_moves.rs @@ -108,7 +108,7 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, Categorization::Downcast(ref b, _) | Categorization::Interior(ref b, mc::InteriorField(_)) | Categorization::Interior(ref b, mc::InteriorElement(Kind::Pattern)) => { - match b.ty.sty { + match b.ty.kind { ty::Adt(def, _) => { if def.has_dtor(bccx.tcx) { Some(cmt.clone()) diff --git a/src/librustc_ast_borrowck/borrowck/gather_loans/restrictions.rs b/src/librustc_ast_borrowck/borrowck/gather_loans/restrictions.rs index 545c27b17bd58..ee5099a97d57f 100644 --- a/src/librustc_ast_borrowck/borrowck/gather_loans/restrictions.rs +++ b/src/librustc_ast_borrowck/borrowck/gather_loans/restrictions.rs @@ -89,7 +89,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { let base_ty = cmt_base.ty; let result = self.restrict(&cmt_base); // Borrowing one union field automatically borrows all its fields. - match base_ty.sty { + match base_ty.kind { ty::Adt(adt_def, _) if adt_def.is_union() => match result { RestrictionResult::Safe => RestrictionResult::Safe, RestrictionResult::SafeIf(base_lp, mut base_vec) => { diff --git a/src/librustc_ast_borrowck/borrowck/move_data.rs b/src/librustc_ast_borrowck/borrowck/move_data.rs index 67d818161b1b5..6bc42348bcf6c 100644 --- a/src/librustc_ast_borrowck/borrowck/move_data.rs +++ b/src/librustc_ast_borrowck/borrowck/move_data.rs @@ -309,7 +309,7 @@ impl MoveData<'tcx> { let mut lp = orig_lp.clone(); while let LpExtend(ref base_lp, mutbl, lp_elem) = lp.clone().kind { if let (&ty::Adt(adt_def, _), LpInterior(opt_variant_id, interior)) - = (&base_lp.ty.sty, lp_elem) { + = (&base_lp.ty.kind, lp_elem) { if adt_def.is_union() { for (i, field) in adt_def.non_enum_variant().fields.iter().enumerate() { let field = @@ -361,7 +361,7 @@ impl MoveData<'tcx> { ) { // Assigning to one union field automatically assigns to all its fields. if let LpExtend(ref base_lp, mutbl, LpInterior(opt_variant_id, interior)) = lp.kind { - if let ty::Adt(adt_def, _) = base_lp.ty.sty { + if let ty::Adt(adt_def, _) = base_lp.ty.kind { if adt_def.is_union() { for (i, field) in adt_def.non_enum_variant().fields.iter().enumerate() { let field = diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 423a01ad1f937..b8b0e77d09830 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -324,7 +324,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { use syntax::ast::UintTy::*; use rustc::ty::{Int, Uint}; - let new_sty = match ty.sty { + let new_sty = match ty.kind { Int(Isize) => Int(self.tcx.sess.target.isize_ty), Uint(Usize) => Uint(self.tcx.sess.target.usize_ty), ref t @ Uint(_) | ref t @ Int(_) => t.clone(), diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index e71d1fc16924b..4fd971ca1153d 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -134,7 +134,7 @@ fn check_and_apply_linkage( // extern "C" fn() from being non-null, so we can't just declare a // static and call it a day. Some linkages (like weak) will make it such // that the static actually has a null value. - let llty2 = if let ty::RawPtr(ref mt) = ty.sty { + let llty2 = if let ty::RawPtr(ref mt) = ty.kind { cx.layout_of(mt.ty).llvm_type(cx) } else { cx.sess().span_fatal( diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index d0b607bd88ee4..02d68f47c7e7d 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -340,7 +340,7 @@ fn fixed_vec_metadata( let (size, align) = cx.size_and_align_of(array_or_slice_type); - let upper_bound = match array_or_slice_type.sty { + let upper_bound = match array_or_slice_type.kind { ty::Array(_, len) => len.eval_usize(cx.tcx, ty::ParamEnv::reveal_all()) as c_longlong, _ => -1 }; @@ -427,7 +427,7 @@ fn subroutine_type_metadata( let signature_metadata: Vec<_> = iter::once( // return type - match signature.output().sty { + match signature.output().kind { ty::Tuple(ref tys) if tys.is_empty() => None, _ => Some(type_metadata(cx, signature.output(), span)) } @@ -466,7 +466,7 @@ fn trait_pointer_metadata( // type is assigned the correct name, size, namespace, and source location. // However, it does not describe the trait's methods. - let containing_scope = match trait_type.sty { + let containing_scope = match trait_type.kind { ty::Dynamic(ref data, ..) => data.principal_def_id().map(|did| get_namespace_for_item(cx, did)), _ => { @@ -563,7 +563,7 @@ pub fn type_metadata( debug!("type_metadata: {:?}", t); let ptr_metadata = |ty: Ty<'tcx>| { - match ty.sty { + match ty.kind { ty::Slice(typ) => { Ok(vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span)) } @@ -591,7 +591,7 @@ pub fn type_metadata( } }; - let MetadataCreationResult { metadata, already_stored_in_typemap } = match t.sty { + let MetadataCreationResult { metadata, already_stored_in_typemap } = match t.kind { ty::Never | ty::Bool | ty::Char | @@ -835,7 +835,7 @@ fn file_metadata_raw(cx: &CodegenCx<'ll, '_>, fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { debug!("basic_type_metadata: {:?}", t); - let (name, encoding) = match t.sty { + let (name, encoding) = match t.kind { ty::Never => ("!", DW_ATE_unsigned), ty::Tuple(ref elements) if elements.is_empty() => ("()", DW_ATE_unsigned), @@ -1145,7 +1145,7 @@ fn prepare_struct_metadata( ) -> RecursiveTypeDescription<'ll, 'tcx> { let struct_name = compute_debuginfo_type_name(cx.tcx, struct_type, false); - let (struct_def_id, variant) = match struct_type.sty { + let (struct_def_id, variant) = match struct_type.kind { ty::Adt(def, _) => (def.did, def.non_enum_variant()), _ => bug!("prepare_struct_metadata on a non-ADT") }; @@ -1268,7 +1268,7 @@ fn prepare_union_metadata( ) -> RecursiveTypeDescription<'ll, 'tcx> { let union_name = compute_debuginfo_type_name(cx.tcx, union_type, false); - let (union_def_id, variant) = match union_type.sty { + let (union_def_id, variant) = match union_type.kind { ty::Adt(def, _) => (def.did, def.non_enum_variant()), _ => bug!("prepare_union_metadata on a non-ADT") }; @@ -1334,7 +1334,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) -> Vec> { let variant_info_for = |index: VariantIdx| { - match &self.enum_type.sty { + match &self.enum_type.kind { ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index]), ty::Generator(def_id, substs, _) => { let generator_layout = cx.tcx.generator_layout(*def_id); @@ -1354,7 +1354,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { match self.layout.variants { layout::Variants::Single { index } => { - if let ty::Adt(adt, _) = &self.enum_type.sty { + if let ty::Adt(adt, _) = &self.enum_type.kind { if adt.variants.is_empty() { return vec![]; } @@ -1747,7 +1747,7 @@ fn prepare_enum_metadata( let file_metadata = unknown_file_metadata(cx); let discriminant_type_metadata = |discr: layout::Primitive| { - let enumerators_metadata: Vec<_> = match enum_type.sty { + let enumerators_metadata: Vec<_> = match enum_type.kind { ty::Adt(def, _) => def .discriminants(cx.tcx) .zip(&def.variants) @@ -1790,7 +1790,7 @@ fn prepare_enum_metadata( let discriminant_base_type_metadata = type_metadata(cx, discr.to_ty(cx.tcx), syntax_pos::DUMMY_SP); - let discriminant_name = match enum_type.sty { + let discriminant_name = match enum_type.kind { ty::Adt(..) => SmallCStr::new(&cx.tcx.item_name(enum_def_id).as_str()), ty::Generator(..) => SmallCStr::new(&enum_name), _ => bug!(), @@ -1881,7 +1881,7 @@ fn prepare_enum_metadata( ); } - let discriminator_name = match &enum_type.sty { + let discriminator_name = match &enum_type.kind { ty::Generator(..) => Some(SmallCStr::new(&"__state")), _ => None, }; @@ -2091,7 +2091,7 @@ fn set_members_of_composite_type(cx: &CodegenCx<'ll, 'tcx>, // Compute the type parameters for a type, if any, for the given // metadata. fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> Option<&'ll DIArray> { - if let ty::Adt(def, substs) = ty.sty { + if let ty::Adt(def, substs) = ty.kind { if !substs.types().next().is_none() { let generics = cx.tcx.generics_of(def.did); let names = get_parameter_names(cx, generics); diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index 6dedf10f0ab83..08a37ce9bbfc8 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -377,7 +377,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { let mut signature = Vec::with_capacity(sig.inputs().len() + 1); // Return type -- llvm::DIBuilder wants this at index 0 - signature.push(match sig.output().sty { + signature.push(match sig.output().kind { ty::Tuple(ref tys) if tys.is_empty() => None, _ => Some(type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP)) }); @@ -401,7 +401,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { // This transformed type is wrong, but these function types are // already inaccurate due to ABI adjustments (see #42800). signature.extend(inputs.iter().map(|&t| { - let t = match t.sty { + let t = match t.kind { ty::Array(ct, _) if (ct == cx.tcx.types.u8) || cx.layout_of(ct).is_zst() => { cx.tcx.mk_imm_ptr(ct) @@ -417,7 +417,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { } if sig.abi == Abi::RustCall && !sig.inputs().is_empty() { - if let ty::Tuple(args) = sig.inputs()[sig.inputs().len() - 1].sty { + if let ty::Tuple(args) = sig.inputs()[sig.inputs().len() - 1].kind { signature.extend( args.iter().map(|argument_type| { Some(type_metadata(cx, argument_type.expect_ty(), syntax_pos::DUMMY_SP)) @@ -516,7 +516,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { // Only "class" methods are generally understood by LLVM, // so avoid methods on other types (e.g., `<*mut T>::null`). - match impl_self_ty.sty { + match impl_self_ty.kind { ty::Adt(def, ..) if !def.is_box() => { Some(type_metadata(cx, impl_self_ty, syntax_pos::DUMMY_SP)) } diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 3f3c5ac1460a3..b7a410c3760cd 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -91,7 +91,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { let tcx = self.tcx; let callee_ty = instance.ty(tcx); - let (def_id, substs) = match callee_ty.sty { + let (def_id, substs) = match callee_ty.kind { ty::FnDef(def_id, substs) => (def_id, substs), _ => bug!("expected fn item type, found {}", callee_ty) }; @@ -1074,7 +1074,7 @@ fn generic_simd_intrinsic( if name == "simd_select_bitmask" { let in_ty = arg_tys[0]; - let m_len = match in_ty.sty { + let m_len = match in_ty.kind { // Note that this `.unwrap()` crashes for isize/usize, that's sort // of intentional as there's not currently a use case for that. ty::Int(i) => i.bit_width().unwrap(), @@ -1203,7 +1203,7 @@ fn generic_simd_intrinsic( "mismatched lengths: mask length `{}` != other vector length `{}`", m_len, v_len ); - match m_elem_ty.sty { + match m_elem_ty.kind { ty::Int(_) => {}, _ => return_error!("mask element type is `{}`, expected `i_`", m_elem_ty) } @@ -1223,7 +1223,7 @@ fn generic_simd_intrinsic( // If the vector has less than 8 lanes, an u8 is returned with zeroed // trailing bits. let expected_int_bits = in_len.max(8); - match ret_ty.sty { + match ret_ty.kind { ty::Uint(i) if i.bit_width() == Some(expected_int_bits) => (), _ => return_error!( "bitmask `{}`, expected `u{}`", @@ -1232,7 +1232,7 @@ fn generic_simd_intrinsic( } // Integer vector : - let (i_xn, in_elem_bitwidth) = match in_elem.sty { + let (i_xn, in_elem_bitwidth) = match in_elem.kind { ty::Int(i) => ( args[0].immediate(), i.bit_width().unwrap_or(bx.data_layout().pointer_size.bits() as _) @@ -1288,7 +1288,7 @@ fn generic_simd_intrinsic( } } } - let ety = match in_elem.sty { + let ety = match in_elem.kind { ty::Float(f) if f.bit_width() == 32 => { if in_len < 2 || in_len > 16 { return_error!( @@ -1375,7 +1375,7 @@ fn generic_simd_intrinsic( // https://github.com/llvm-mirror/llvm/blob/master/include/llvm/IR/Intrinsics.h#L81 fn llvm_vector_str(elem_ty: Ty<'_>, vec_len: usize, no_pointers: usize) -> String { let p0s: String = "p0".repeat(no_pointers); - match elem_ty.sty { + match elem_ty.kind { ty::Int(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()), ty::Uint(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()), ty::Float(v) => format!("v{}{}f{}", vec_len, p0s, v.bit_width()), @@ -1386,7 +1386,7 @@ fn generic_simd_intrinsic( fn llvm_vector_ty(cx: &CodegenCx<'ll, '_>, elem_ty: Ty<'_>, vec_len: usize, mut no_pointers: usize) -> &'ll Type { // FIXME: use cx.layout_of(ty).llvm_type() ? - let mut elem_ty = match elem_ty.sty { + let mut elem_ty = match elem_ty.kind { ty::Int(v) => cx.type_int_from_ty( v), ty::Uint(v) => cx.type_uint_from_ty( v), ty::Float(v) => cx.type_float_from_ty( v), @@ -1430,7 +1430,7 @@ fn generic_simd_intrinsic( // This counts how many pointers fn ptr_count(t: Ty<'_>) -> usize { - match t.sty { + match t.kind { ty::RawPtr(p) => 1 + ptr_count(p.ty), _ => 0, } @@ -1438,7 +1438,7 @@ fn generic_simd_intrinsic( // Non-ptr type fn non_ptr(t: Ty<'_>) -> Ty<'_> { - match t.sty { + match t.kind { ty::RawPtr(p) => non_ptr(p.ty), _ => t, } @@ -1446,7 +1446,7 @@ fn generic_simd_intrinsic( // The second argument must be a simd vector with an element type that's a pointer // to the element type of the first argument - let (pointer_count, underlying_ty) = match arg_tys[1].simd_type(tcx).sty { + let (pointer_count, underlying_ty) = match arg_tys[1].simd_type(tcx).kind { ty::RawPtr(p) if p.ty == in_elem => (ptr_count(arg_tys[1].simd_type(tcx)), non_ptr(arg_tys[1].simd_type(tcx))), _ => { @@ -1463,7 +1463,7 @@ fn generic_simd_intrinsic( assert_eq!(underlying_ty, non_ptr(arg_tys[0].simd_type(tcx))); // The element type of the third argument must be a signed integer type of any width: - match arg_tys[2].simd_type(tcx).sty { + match arg_tys[2].simd_type(tcx).kind { ty::Int(_) => (), _ => { require!(false, "expected element type `{}` of third argument `{}` \ @@ -1529,7 +1529,7 @@ fn generic_simd_intrinsic( // This counts how many pointers fn ptr_count(t: Ty<'_>) -> usize { - match t.sty { + match t.kind { ty::RawPtr(p) => 1 + ptr_count(p.ty), _ => 0, } @@ -1537,7 +1537,7 @@ fn generic_simd_intrinsic( // Non-ptr type fn non_ptr(t: Ty<'_>) -> Ty<'_> { - match t.sty { + match t.kind { ty::RawPtr(p) => non_ptr(p.ty), _ => t, } @@ -1545,7 +1545,7 @@ fn generic_simd_intrinsic( // The second argument must be a simd vector with an element type that's a pointer // to the element type of the first argument - let (pointer_count, underlying_ty) = match arg_tys[1].simd_type(tcx).sty { + let (pointer_count, underlying_ty) = match arg_tys[1].simd_type(tcx).kind { ty::RawPtr(p) if p.ty == in_elem && p.mutbl == hir::MutMutable => (ptr_count(arg_tys[1].simd_type(tcx)), non_ptr(arg_tys[1].simd_type(tcx))), @@ -1563,7 +1563,7 @@ fn generic_simd_intrinsic( assert_eq!(underlying_ty, non_ptr(arg_tys[0].simd_type(tcx))); // The element type of the third argument must be a signed integer type of any width: - match arg_tys[2].simd_type(tcx).sty { + match arg_tys[2].simd_type(tcx).kind { ty::Int(_) => (), _ => { require!(false, "expected element type `{}` of third argument `{}` \ @@ -1612,7 +1612,7 @@ fn generic_simd_intrinsic( require!(ret_ty == in_elem, "expected return type `{}` (element of input `{}`), found `{}`", in_elem, in_ty, ret_ty); - return match in_elem.sty { + return match in_elem.kind { ty::Int(_) | ty::Uint(_) => { let r = bx.$integer_reduce(args[0].immediate()); if $ordered { @@ -1669,7 +1669,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, require!(ret_ty == in_elem, "expected return type `{}` (element of input `{}`), found `{}`", in_elem, in_ty, ret_ty); - return match in_elem.sty { + return match in_elem.kind { ty::Int(_i) => { Ok(bx.$int_red(args[0].immediate(), true)) }, @@ -1704,7 +1704,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, in_elem, in_ty, ret_ty); args[0].immediate() } else { - match in_elem.sty { + match in_elem.kind { ty::Int(_) | ty::Uint(_) => {}, _ => { return_error!("unsupported {} from `{}` with element `{}` to `{}`", @@ -1717,7 +1717,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, let i1xn = bx.type_vector(i1, in_len as u64); bx.trunc(args[0].immediate(), i1xn) }; - return match in_elem.sty { + return match in_elem.kind { ty::Int(_) | ty::Uint(_) => { let r = bx.$red(input); Ok( @@ -1758,7 +1758,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, enum Style { Float, Int(/* is signed? */ bool), Unsupported } - let (in_style, in_width) = match in_elem.sty { + let (in_style, in_width) = match in_elem.kind { // vectors of pointer-sized integers should've been // disallowed before here, so this unwrap is safe. ty::Int(i) => (Style::Int(true), i.bit_width().unwrap()), @@ -1766,7 +1766,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, ty::Float(f) => (Style::Float, f.bit_width()), _ => (Style::Unsupported, 0) }; - let (out_style, out_width) = match out_elem.sty { + let (out_style, out_width) = match out_elem.kind { ty::Int(i) => (Style::Int(true), i.bit_width().unwrap()), ty::Uint(u) => (Style::Int(false), u.bit_width().unwrap()), ty::Float(f) => (Style::Float, f.bit_width()), @@ -1816,7 +1816,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, macro_rules! arith { ($($name: ident: $($($p: ident),* => $call: ident),*;)*) => { $(if name == stringify!($name) { - match in_elem.sty { + match in_elem.kind { $($(ty::$p(_))|* => { return Ok(bx.$call(args[0].immediate(), args[1].immediate())) })* @@ -1850,7 +1850,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, let rhs = args[1].immediate(); let is_add = name == "simd_saturating_add"; let ptr_bits = bx.tcx().data_layout.pointer_size.bits() as _; - let (signed, elem_width, elem_ty) = match in_elem.sty { + let (signed, elem_width, elem_ty) = match in_elem.kind { ty::Int(i) => ( true, @@ -1896,7 +1896,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, // FIXME: there’s multiple of this functions, investigate using some of the already existing // stuffs. fn int_type_width_signed(ty: Ty<'_>, cx: &CodegenCx<'_, '_>) -> Option<(u64, bool)> { - match ty.sty { + match ty.kind { ty::Int(t) => Some((match t { ast::IntTy::Isize => cx.tcx.sess.target.isize_ty.bit_width().unwrap() as u64, ast::IntTy::I8 => 8, @@ -1920,7 +1920,7 @@ fn int_type_width_signed(ty: Ty<'_>, cx: &CodegenCx<'_, '_>) -> Option<(u64, boo // Returns the width of a float Ty // Returns None if the type is not a float fn float_type_width(ty: Ty<'_>) -> Option { - match ty.sty { + match ty.kind { ty::Float(t) => Some(t.bit_width() as u64), _ => None, } diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index 36a9ff0a2d2e5..81a99bc5019b3 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -43,7 +43,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, layout::Abi::Aggregate { .. } => {} } - let name = match layout.ty.sty { + let name = match layout.ty.kind { ty::Closure(..) | ty::Generator(..) | ty::Adt(..) | @@ -56,14 +56,14 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let printer = DefPathBasedNames::new(cx.tcx, true, true); printer.push_type_name(layout.ty, &mut name, false); if let (&ty::Adt(def, _), &layout::Variants::Single { index }) - = (&layout.ty.sty, &layout.variants) + = (&layout.ty.kind, &layout.variants) { if def.is_enum() && !def.variants.is_empty() { write!(&mut name, "::{}", def.variants[index].ident).unwrap(); } } if let (&ty::Generator(_, substs, _), &layout::Variants::Single { index }) - = (&layout.ty.sty, &layout.variants) + = (&layout.ty.kind, &layout.variants) { write!(&mut name, "::{}", substs.variant_name(index)).unwrap(); } @@ -226,7 +226,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { if let Some(&llty) = cx.scalar_lltypes.borrow().get(&self.ty) { return llty; } - let llty = match self.ty.sty { + let llty = match self.ty.kind { ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => { cx.type_ptr_to(cx.layout_of(ty).llvm_type(cx)) @@ -318,7 +318,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { index: usize, immediate: bool) -> &'a Type { // HACK(eddyb) special-case fat pointers until LLVM removes // pointee types, to avoid bitcasting every `OperandRef::deref`. - match self.ty.sty { + match self.ty.kind { ty::Ref(..) | ty::RawPtr(_) => { return self.field(cx, index).llvm_type(cx); diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 98d3022a4185d..8f7f769f6b996 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -96,7 +96,7 @@ pub fn compare_simd_types<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ret_ty: Bx::Type, op: hir::BinOpKind, ) -> Bx::Value { - let signed = match t.sty { + let signed = match t.kind { ty::Float(_) => { let cmp = bin_op_to_fcmp_predicate(op); let cmp = bx.fcmp(cmp, lhs, rhs); @@ -130,7 +130,7 @@ pub fn unsized_info<'tcx, Cx: CodegenMethods<'tcx>>( ) -> Cx::Value { let (source, target) = cx.tcx().struct_lockstep_tails_erasing_lifetimes(source, target, cx.param_env()); - match (&source.sty, &target.sty) { + match (&source.kind, &target.kind) { (&ty::Array(_, len), &ty::Slice(_)) => { cx.const_usize(len.eval_usize(cx.tcx(), ty::ParamEnv::reveal_all())) } @@ -160,7 +160,7 @@ pub fn unsize_thin_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( dst_ty: Ty<'tcx>, ) -> (Bx::Value, Bx::Value) { debug!("unsize_thin_ptr: {:?} => {:?}", src_ty, dst_ty); - match (&src_ty.sty, &dst_ty.sty) { + match (&src_ty.kind, &dst_ty.kind) { (&ty::Ref(_, a, _), &ty::Ref(_, b, _)) | (&ty::Ref(_, a, _), @@ -232,7 +232,7 @@ pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( }; OperandValue::Pair(base, info).store(bx, dst); }; - match (&src_ty.sty, &dst_ty.sty) { + match (&src_ty.kind, &dst_ty.kind) { (&ty::Ref(..), &ty::Ref(..)) | (&ty::Ref(..), &ty::RawPtr(..)) | (&ty::RawPtr(..), &ty::RawPtr(..)) => { diff --git a/src/librustc_codegen_ssa/debuginfo/type_names.rs b/src/librustc_codegen_ssa/debuginfo/type_names.rs index 9b5ad94ecd7cb..d875c60959cba 100644 --- a/src/librustc_codegen_ssa/debuginfo/type_names.rs +++ b/src/librustc_codegen_ssa/debuginfo/type_names.rs @@ -32,7 +32,7 @@ pub fn push_debuginfo_type_name<'tcx>( // .natvis visualizers (and perhaps other existing native debuggers?) let cpp_like_names = tcx.sess.target.target.options.is_like_msvc; - match t.sty { + match t.kind { ty::Bool => output.push_str("bool"), ty::Char => output.push_str("char"), ty::Str => output.push_str("str"), diff --git a/src/librustc_codegen_ssa/glue.rs b/src/librustc_codegen_ssa/glue.rs index 7fd9f67e2f45b..9818bb78e757b 100644 --- a/src/librustc_codegen_ssa/glue.rs +++ b/src/librustc_codegen_ssa/glue.rs @@ -20,7 +20,7 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let align = bx.const_usize(layout.align.abi.bytes()); return (size, align); } - match t.sty { + match t.kind { ty::Dynamic(..) => { // load size/align from vtable let vtable = info.unwrap(); @@ -64,7 +64,7 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let size = bx.add(sized_size, unsized_size); // Packed types ignore the alignment of their fields. - if let ty::Adt(def, _) = t.sty { + if let ty::Adt(def, _) = t.kind { if def.repr.packed() { unsized_align = sized_align; } diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index d192f2ffb6fba..05896523863c2 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -218,7 +218,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx> mir::TerminatorKind::Call { func: mir::Operand::Constant(ref c), ref args, .. - } => match c.literal.ty.sty { + } => match c.literal.ty.kind { ty::FnDef(did, _) => Some((did, args)), _ => None, }, diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 1bb0ea5dae44b..3069199a21256 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -323,7 +323,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { args1 = [place.llval]; &args1[..] }; - let (drop_fn, fn_ty) = match ty.sty { + let (drop_fn, fn_ty) = match ty.kind { ty::Dynamic(..) => { let sig = drop_fn.fn_sig(self.cx.tcx()); let sig = self.cx.tcx().normalize_erasing_late_bound_regions( @@ -455,7 +455,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar. let callee = self.codegen_operand(&mut bx, func); - let (instance, mut llfn) = match callee.layout.ty.sty { + let (instance, mut llfn) = match callee.layout.ty.kind { ty::FnDef(def_id, substs) => { (Some(ty::Instance::resolve(bx.tcx(), ty::ParamEnv::reveal_all(), diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index 216e5a4645a46..9cfe410fcc5e0 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -40,7 +40,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { constant .map(|c| { let field_ty = c.ty.builtin_index().unwrap(); - let fields = match c.ty.sty { + let fields = match c.ty.kind { ty::Array(_, n) => n.eval_usize(bx.tcx(), ty::ParamEnv::reveal_all()), _ => bug!("invalid simd shuffle type: {}", c.ty), }; diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index aa3971a1da81a..c341c0685c6a7 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -467,7 +467,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // individual LLVM function arguments. let arg_ty = fx.monomorphize(&arg_decl.ty); - let tupled_arg_tys = match arg_ty.sty { + let tupled_arg_tys = match arg_ty.kind { ty::Tuple(ref tys) => tys, _ => bug!("spread argument isn't a tuple?!") }; @@ -573,7 +573,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( Some(did) => did, None => bug!("`va_list` lang item required for C-variadic functions"), }; - match arg_decl.ty.sty { + match arg_decl.ty.kind { ty::Adt(def, _) if def.did == va_list_did => { // Call `va_start` on the spoofed `VaListImpl`. bx.va_start(tmp.llval); @@ -612,11 +612,11 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let pin_did = tcx.lang_items().pin_type(); // Or is it the closure environment? - let (closure_layout, env_ref) = match arg.layout.ty.sty { + let (closure_layout, env_ref) = match arg.layout.ty.kind { ty::RawPtr(ty::TypeAndMut { ty, .. }) | ty::Ref(_, ty, _) => (bx.layout_of(ty), true), ty::Adt(def, substs) if Some(def.did) == pin_did => { - match substs.type_at(0).sty { + match substs.type_at(0).kind { ty::Ref(_, ty, _) => (bx.layout_of(ty), true), _ => (arg.layout, false), } @@ -624,7 +624,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( _ => (arg.layout, false) }; - let (def_id, upvar_substs) = match closure_layout.ty.sty { + let (def_id, upvar_substs) = match closure_layout.ty.kind { ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)), ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)), _ => bug!("upvar debuginfo with non-closure arg0 type `{}`", closure_layout.ty) @@ -641,7 +641,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( }); let generator_fields = mir.generator_layout.as_ref().map(|generator_layout| { - let (def_id, gen_substs) = match closure_layout.ty.sty { + let (def_id, gen_substs) = match closure_layout.ty.kind { ty::Generator(def_id, substs, _) => (def_id, substs), _ => bug!("generator layout without generator substs"), }; @@ -695,7 +695,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // The environment and the capture can each be indirect. let mut ops = if env_ref { &ops[..] } else { &ops[1..] }; - let ty = if let (true, &ty::Ref(_, ty, _)) = (by_ref, &ty.sty) { + let ty = if let (true, &ty::Ref(_, ty, _)) = (by_ref, &ty.kind) { ty } else { ops = &ops[..ops.len() - 1]; diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index a4b4cb53bb1fb..2d97f828f073d 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -144,7 +144,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { // * no metadata available - just log the case // * known alignment - sized types, `[T]`, `str` or a foreign type // * packed struct - there is no alignment padding - match field.ty.sty { + match field.ty.kind { _ if self.llextra.is_none() => { debug!("unsized field `{}`, of `{:?}` has no metadata for adjustment", ix, self.llval); diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index f21836a953c22..9b69383b455cf 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -184,7 +184,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let val = match *kind { mir::CastKind::Pointer(PointerCast::ReifyFnPointer) => { - match operand.layout.ty.sty { + match operand.layout.ty.kind { ty::FnDef(def_id, substs) => { if bx.cx().tcx().has_attr(def_id, sym::rustc_args_required_const) { bug!("reifying a fn ptr that requires const arguments"); @@ -198,7 +198,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } mir::CastKind::Pointer(PointerCast::ClosureFnPointer(_)) => { - match operand.layout.ty.sty { + match operand.layout.ty.kind { ty::Closure(def_id, substs) => { let instance = Instance::resolve_closure( bx.cx().tcx(), def_id, substs, ty::ClosureKind::FnOnce); @@ -525,7 +525,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { projection: box [], } = *place { if let LocalRef::Operand(Some(op)) = self.locals[index] { - if let ty::Array(_, n) = op.layout.ty.sty { + if let ty::Array(_, n) = op.layout.ty.kind { let n = n.eval_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all()); return bx.cx().const_usize(n); } diff --git a/src/librustc_codegen_ssa/traits/type_.rs b/src/librustc_codegen_ssa/traits/type_.rs index 13f72e23819a1..19d41c6b37cbb 100644 --- a/src/librustc_codegen_ssa/traits/type_.rs +++ b/src/librustc_codegen_ssa/traits/type_.rs @@ -83,7 +83,7 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> { } let tail = self.tcx().struct_tail_erasing_lifetimes(ty, param_env); - match tail.sty { + match tail.kind { ty::Foreign(..) => false, ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, _ => bug!("unexpected unsized tail: {:?}", tail), diff --git a/src/librustc_codegen_utils/symbol_names/legacy.rs b/src/librustc_codegen_utils/symbol_names/legacy.rs index 22b7e0a2fb0c9..1b094e26c2443 100644 --- a/src/librustc_codegen_utils/symbol_names/legacy.rs +++ b/src/librustc_codegen_utils/symbol_names/legacy.rs @@ -111,7 +111,7 @@ fn get_symbol_hash<'tcx>( // If this is a function, we hash the signature as well. // This is not *strictly* needed, but it may help in some // situations, see the `run-make/a-b-a-linker-guard` test. - if let ty::FnDef(..) = item_type.sty { + if let ty::FnDef(..) = item_type.kind { item_type.fn_sig(tcx).hash_stable(&mut hcx, &mut hasher); } @@ -218,7 +218,7 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> { self, ty: Ty<'tcx>, ) -> Result { - match ty.sty { + match ty.kind { // Print all nominal types as paths (unlike `pretty_print_type`). ty::FnDef(def_id, substs) | ty::Opaque(def_id, substs) | @@ -275,7 +275,7 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> { ) -> Result { // Similar to `pretty_path_qualified`, but for the other // types that are printed as paths (see `print_type` above). - match self_ty.sty { + match self_ty.kind { ty::FnDef(..) | ty::Opaque(..) | ty::Projection(_) | diff --git a/src/librustc_codegen_utils/symbol_names/v0.rs b/src/librustc_codegen_utils/symbol_names/v0.rs index 8d6a1d757e014..f1f5913425d01 100644 --- a/src/librustc_codegen_utils/symbol_names/v0.rs +++ b/src/librustc_codegen_utils/symbol_names/v0.rs @@ -323,7 +323,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { ty: Ty<'tcx>, ) -> Result { // Basic types, never cached (single-character). - let basic_type = match ty.sty { + let basic_type = match ty.kind { ty::Bool => "b", ty::Char => "c", ty::Str => "e", @@ -360,7 +360,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { } let start = self.out.len(); - match ty.sty { + match ty.kind { // Basic types, handled above. ty::Bool | ty::Char | ty::Str | ty::Int(_) | ty::Uint(_) | ty::Float(_) | @@ -511,7 +511,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { } let start = self.out.len(); - match ct.ty.sty { + match ct.ty.kind { ty::Uint(_) => {} _ => { bug!("symbol_names: unsupported constant of type `{}` ({:?})", diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index cf19a9eb147a8..d08fd47dc169e 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -918,7 +918,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes { let msg = "mutating transmuted &mut T from &T may cause undefined behavior, \ consider instead using an UnsafeCell"; - match get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (&ty1.sty, &ty2.sty)) { + match get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (&ty1.kind, &ty2.kind)) { Some((&ty::Ref(_, _, from_mt), &ty::Ref(_, _, to_mt))) => { if to_mt == hir::Mutability::MutMutable && from_mt == hir::Mutability::MutImmutable { @@ -1954,7 +1954,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { init: InitKind, ) -> Option { use rustc::ty::TyKind::*; - match ty.sty { + match ty.kind { // Primitive types that don't like 0 as a value. Ref(..) => Some((format!("References must be non-null"), None)), Adt(..) if ty.is_box() => Some((format!("`Box` must be non-null"), None)), diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 40261f6d13739..3a037b4dfff1f 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -227,7 +227,7 @@ fn get_type_suggestion(t: Ty<'_>, val: u128, negative: bool) -> Option { } } } - match t.sty { + match t.kind { ty::Int(i) => find_fit!(i, val, negative, I8 => [U8] => [I16, I32, I64, I128], I16 => [U16] => [I32, I64, I128], @@ -320,7 +320,7 @@ fn lint_uint_literal<'a, 'tcx>( if let Node::Expr(par_e) = cx.tcx.hir().get(parent_id) { match par_e.node { hir::ExprKind::Cast(..) => { - if let ty::Char = cx.tables.expr_ty(par_e).sty { + if let ty::Char = cx.tables.expr_ty(par_e).kind { let mut err = cx.struct_span_lint( OVERFLOWING_LITERALS, par_e.span, @@ -364,7 +364,7 @@ fn lint_literal<'a, 'tcx>( e: &'tcx hir::Expr, lit: &hir::Lit, ) { - match cx.tables.node_type(e.hir_id).sty { + match cx.tables.node_type(e.hir_id).kind { ty::Int(t) => { match lit.node { ast::LitKind::Int(v, ast::LitIntType::Signed(_)) | @@ -453,7 +453,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { // Normalize the binop so that the literal is always on the RHS in // the comparison let norm_binop = if swap { rev_binop(binop) } else { binop }; - match cx.tables.node_type(expr.hir_id).sty { + match cx.tables.node_type(expr.hir_id).kind { ty::Int(int_ty) => { let (min, max) = int_ty_range(int_ty); let lit_val: i128 = match lit.node { @@ -526,7 +526,7 @@ fn is_zst<'tcx>(tcx: TyCtxt<'tcx>, did: DefId, ty: Ty<'tcx>) -> bool { } fn ty_is_known_nonnull<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { - match ty.sty { + match ty.kind { ty::FnPtr(_) => true, ty::Ref(..) => true, ty::Adt(field_def, substs) if field_def.repr.transparent() && !field_def.is_union() => { @@ -615,7 +615,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { return FfiSafe; } - match ty.sty { + match ty.kind { ty::Adt(def, substs) => { if def.is_phantom_data() { return FfiPhantom(ty); @@ -876,7 +876,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { diag.help(help); } diag.note(note); - if let ty::Adt(def, _) = ty.sty { + if let ty::Adt(def, _) = ty.kind { if let Some(sp) = self.cx.tcx.hir().span_if_local(def.did) { diag.span_note(sp, "type defined here"); } @@ -893,7 +893,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'tcx> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { - if let ty::Opaque(..) = ty.sty { + if let ty::Opaque(..) = ty.kind { self.ty = Some(ty); true } else { diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 2d4af2f606a2c..86df0b9f681e4 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -145,7 +145,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { let plural_suffix = pluralise!(plural_len); - match ty.sty { + match ty.kind { ty::Adt(..) if ty.is_box() => { let boxed_ty = ty.boxed_ty(); let descr_pre = &format!("{}boxed ", descr_pre); diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 965a8658c9592..38089f0dc7391 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1427,7 +1427,7 @@ impl EncodeContext<'tcx> { let tables = self.tcx.typeck_tables_of(def_id); let hir_id = self.tcx.hir().as_local_hir_id(def_id).unwrap(); - let kind = match tables.node_type(hir_id).sty { + let kind = match tables.node_type(hir_id).kind { ty::Generator(def_id, ..) => { let layout = self.tcx.generator_layout(def_id); let data = GeneratorData { @@ -1978,7 +1978,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { pub fn get_repr_options(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions { let ty = tcx.type_of(did); - match ty.sty { + match ty.kind { ty::Adt(ref def, _) => return def.repr, _ => bug!("{} is not an ADT", ty), } diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index 599a0ad0d0c52..5fb41dc20c741 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -211,7 +211,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let ty = Place::ty_from(used_place.base, used_place.projection, self.body, self.infcx.tcx) .ty; - let needs_note = match ty.sty { + let needs_note = match ty.kind { ty::Closure(id, _) => { let tables = self.infcx.tcx.typeck_tables_of(id); let hir_id = self.infcx.tcx.hir().as_local_hir_id(id).unwrap(); @@ -232,7 +232,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Some(ref name) => format!("`{}`", name), None => "value".to_owned(), }; - if let ty::Param(param_ty) = ty.sty { + if let ty::Param(param_ty) = ty.kind { let tcx = self.infcx.tcx; let generics = tcx.generics_of(self.mir_def_id); let def_id = generics.type_param(¶m_ty, tcx).def_id; @@ -1243,7 +1243,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let escapes_from = if tcx.is_closure(self.mir_def_id) { let tables = tcx.typeck_tables_of(self.mir_def_id); let mir_hir_id = tcx.hir().def_index_to_hir_id(self.mir_def_id.index); - match tables.node_type(mir_hir_id).sty { + match tables.node_type(mir_hir_id).kind { ty::Closure(..) => "closure", ty::Generator(..) => "generator", _ => bug!("Closure body doesn't have a closure or generator type"), @@ -1543,7 +1543,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }, ProjectionElem::Field(..) | ProjectionElem::Downcast(..) => { let base_ty = Place::ty_from(&place.base, proj_base, self.body, tcx).ty; - match base_ty.sty { + match base_ty.kind { ty::Adt(def, _) if def.has_dtor(tcx) => { // Report the outermost adt with a destructor match base_access { @@ -1579,7 +1579,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { None } else { let ty = self.infcx.tcx.type_of(self.mir_def_id); - match ty.sty { + match ty.kind { ty::FnDef(_, _) | ty::FnPtr(_) => self.annotate_fn_sig( self.mir_def_id, self.infcx.tcx.fn_sig(self.mir_def_id), @@ -1834,13 +1834,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // 3. The return type is not a reference. In this case, we don't highlight // anything. let return_ty = sig.output(); - match return_ty.skip_binder().sty { + match return_ty.skip_binder().kind { ty::Ref(return_region, _, _) if return_region.has_name() && !is_closure => { // This is case 1 from above, return type is a named reference so we need to // search for relevant arguments. let mut arguments = Vec::new(); for (index, argument) in sig.inputs().skip_binder().iter().enumerate() { - if let ty::Ref(argument_region, _, _) = argument.sty { + if let ty::Ref(argument_region, _, _) = argument.kind { if argument_region == return_region { // Need to use the `rustc::ty` types to compare against the // `return_region`. Then use the `rustc::hir` type to get only @@ -1886,9 +1886,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Closure arguments are wrapped in a tuple, so we need to get the first // from that. - if let ty::Tuple(elems) = argument_ty.sty { + if let ty::Tuple(elems) = argument_ty.kind { let argument_ty = elems.first()?.expect_ty(); - if let ty::Ref(_, _, _) = argument_ty.sty { + if let ty::Ref(_, _, _) = argument_ty.kind { return Some(AnnotatedBorrowFnSignature::Closure { argument_ty, argument_span, @@ -1908,7 +1908,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let return_ty = *sig.output().skip_binder(); // We expect the first argument to be a reference. - match argument_ty.sty { + match argument_ty.kind { ty::Ref(_, _, _) => {} _ => return None, } diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 5bccd2835c980..c0c0e7a32b672 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -58,7 +58,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let TerminatorKind::Call { func: Operand::Constant(box Constant { literal: ty::Const { - ty: &ty::TyS { sty: ty::FnDef(id, _), .. }, + ty: &ty::TyS { kind: ty::FnDef(id, _), .. }, .. }, .. @@ -76,7 +76,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; debug!("add_moved_or_invoked_closure_note: closure={:?}", closure); - if let ty::Closure(did, _) = self.body.local_decls[closure].ty.sty { + if let ty::Closure(did, _) = self.body.local_decls[closure].ty.kind { let hir_id = self.infcx.tcx.hir().as_local_hir_id(did).unwrap(); if let Some((span, name)) = self.infcx.tcx.typeck_tables_of(did) @@ -99,7 +99,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Check if we are just moving a closure after it has been invoked. if let Some(target) = target { - if let ty::Closure(did, _) = self.body.local_decls[target].ty.sty { + if let ty::Closure(did, _) = self.body.local_decls[target].ty.kind { let hir_id = self.infcx.tcx.hir().as_local_hir_id(did).unwrap(); if let Some((span, name)) = self.infcx.tcx.typeck_tables_of(did) @@ -400,7 +400,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // If the type is a box, the field is described from the boxed type self.describe_field_from_ty(&ty.boxed_ty(), field, variant_index) } else { - match ty.sty { + match ty.kind { ty::Adt(def, _) => { let variant = if let Some(idx) = variant_index { assert!(def.is_enum()); @@ -558,7 +558,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // We need to add synthesized lifetimes where appropriate. We do // this by hooking into the pretty printer and telling it to label the // lifetimes without names with the value `'0`. - match ty.sty { + match ty.kind { ty::Ref(ty::RegionKind::ReLateBound(_, br), _, _) | ty::Ref( ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }), @@ -578,7 +578,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut s = String::new(); let mut printer = ty::print::FmtPrinter::new(self.infcx.tcx, &mut s, Namespace::TypeNS); - let region = match ty.sty { + let region = match ty.kind { ty::Ref(region, _, _) => { match region { ty::RegionKind::ReLateBound(_, br) @@ -754,7 +754,7 @@ impl BorrowedContentSource<'tcx> { } fn from_call(func: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Option { - match func.sty { + match func.kind { ty::FnDef(def_id, substs) => { let trait_id = tcx.trait_of_item(def_id)?; diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 32c6dd67a4b5a..b12af1a0e9522 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1796,7 +1796,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // be already initialized let tcx = self.infcx.tcx; let base_ty = Place::ty_from(&place.base, proj_base, self.body, tcx).ty; - match base_ty.sty { + match base_ty.kind { ty::Adt(def, _) if def.has_dtor(tcx) => { self.check_if_path_or_subpath_is_moved( location, InitializationRequiringAction::Assignment, @@ -1902,7 +1902,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // of the union - we should error in that case. let tcx = this.infcx.tcx; if let ty::Adt(def, _) = - Place::ty_from(base.base, base.projection, this.body, tcx).ty.sty + Place::ty_from(base.base, base.projection, this.body, tcx).ty.kind { if def.is_union() { if this.move_data.path_map[mpi].iter().any(|moi| { @@ -2195,7 +2195,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Place::ty_from(place.base, proj_base, self.body, self.infcx.tcx).ty; // Check the kind of deref to decide - match base_ty.sty { + match base_ty.kind { ty::Ref(_, _, mutbl) => { match mutbl { // Shared borrowed data is never mutable diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index aa732b0092a22..bf5bddadd16f1 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -335,7 +335,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } debug!("report: ty={:?}", ty); - let mut err = match ty.sty { + let mut err = match ty.kind { ty::Array(..) | ty::Slice(..) => self.cannot_move_out_of_interior_noncopy(span, ty, None), ty::Closure(def_id, closure_substs) diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 14b76d97b3e57..c3aed74bcaad2 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -283,7 +283,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // for a `self: &mut Self` to suggest removing the `&mut`. if let ty::Ref( _, _, hir::Mutability::MutMutable - ) = local_decl.ty.sty { + ) = local_decl.ty.kind { true } else { false @@ -630,8 +630,8 @@ fn annotate_struct_field( field: &mir::Field, ) -> Option<(Span, String)> { // Expect our local to be a reference to a struct of some kind. - if let ty::Ref(_, ty, _) = ty.sty { - if let ty::Adt(def, _) = ty.sty { + if let ty::Ref(_, ty, _) = ty.kind { + if let ty::Adt(def, _) = ty.kind { let field = def.all_fields().nth(field.index())?; // Use the HIR types to construct the diagnostic message. let hir_id = tcx.hir().as_local_hir_id(field.did)?; diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index eae2f832ba791..ff4243df6e9b8 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -95,7 +95,7 @@ impl BorrowExplanation { should_note_order, } => { let local_decl = &body.local_decls[dropped_local]; - let (dtor_desc, type_desc) = match local_decl.ty.sty { + let (dtor_desc, type_desc) = match local_decl.ty.kind { // If type is an ADT that implements Drop, then // simplify output by reporting just the ADT name. ty::Adt(adt, _substs) if adt.has_dtor(tcx) && !adt.is_box() => ( @@ -612,7 +612,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { { debug!("was_captured_by_trait_object: ty={:?}", ty); // Check the type for a trait object. - return match ty.sty { + return match ty.kind { // `&dyn Trait` ty::Ref(_, ty, _) if ty.is_trait() => true, // `Box` diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs index 26a89b4e7a8d1..e29e9232012bc 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs @@ -627,7 +627,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { (self.to_error_region(fr), self.to_error_region(outlived_fr)) { if let Some(ty::TyS { - sty: ty::Opaque(did, substs), + kind: ty::Opaque(did, substs), .. }) = infcx .tcx diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index 6fa94269107f5..ff77083a34dfa 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -527,7 +527,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { &mut vec![(argument_ty, argument_hir_ty)]; while let Some((ty, hir_ty)) = search_stack.pop() { - match (&ty.sty, &hir_ty.node) { + match (&ty.kind, &hir_ty.node) { // Check if the `argument_ty` is `&'X ..` where `'X` // is the region we are looking for -- if so, and we have a `&T` // on the RHS, then we want to highlight the `&` like so: diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 6a764b19c4ddf..4996ea83ae04e 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -314,7 +314,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { ); } } - if let ty::FnDef(def_id, substs) = constant.literal.ty.sty { + if let ty::FnDef(def_id, substs) = constant.literal.ty.kind { let tcx = self.tcx(); let instantiated_predicates = tcx @@ -342,7 +342,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { let ty = if !local_decl.is_nonref_binding() { // If we have a binding of the form `let ref x: T = ..` then remove the outermost // reference so we can check the type annotation for the remaining type. - if let ty::Ref(_, rty, _) = local_decl.ty.sty { + if let ty::Ref(_, rty, _) = local_decl.ty.kind { rty } else { bug!("{:?} with ref binding has wrong type {}", local, local_decl.ty); @@ -637,7 +637,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { ) } ProjectionElem::Subslice { from, to } => PlaceTy::from_ty( - match base_ty.sty { + match base_ty.kind { ty::Array(inner, size) => { let size = size.eval_usize(tcx, self.cx.param_env); let min_size = (from as u64) + (to as u64); @@ -656,7 +656,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { _ => span_mirbug_and_err!(self, place, "slice of non-array {:?}", base_ty), }, ), - ProjectionElem::Downcast(maybe_name, index) => match base_ty.sty { + ProjectionElem::Downcast(maybe_name, index) => match base_ty.kind { ty::Adt(adt_def, _substs) if adt_def.is_enum() => { if index.as_usize() >= adt_def.variants.len() { PlaceTy::from_ty( @@ -738,7 +738,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { let tcx = self.tcx(); let (variant, substs) = match base_ty { - PlaceTy { ty, variant_index: Some(variant_index) } => match ty.sty { + PlaceTy { ty, variant_index: Some(variant_index) } => match ty.kind { ty::Adt(adt_def, substs) => (&adt_def.variants[variant_index], substs), ty::Generator(def_id, substs, _) => { let mut variants = substs.state_tys(def_id, tcx); @@ -759,7 +759,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } _ => bug!("can't have downcast of non-adt non-generator type"), } - PlaceTy { ty, variant_index: None } => match ty.sty { + PlaceTy { ty, variant_index: None } => match ty.kind { ty::Adt(adt_def, substs) if !adt_def.is_enum() => (&adt_def.variants[VariantIdx::new(0)], substs), ty::Closure(def_id, substs) => { @@ -1142,7 +1142,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { category: ConstraintCategory, ) -> Fallible<()> { if let Err(terr) = self.sub_types(sub, sup, locations, category) { - if let ty::Opaque(..) = sup.sty { + if let ty::Opaque(..) = sup.kind { // When you have `let x: impl Foo = ...` in a closure, // the resulting inferend values are stored with the // def-id of the base function. @@ -1430,7 +1430,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { variant_index, } => { let place_type = place.ty(body, tcx).ty; - let adt = match place_type.sty { + let adt = match place_type.kind { ty::Adt(adt, _) if adt.is_enum() => adt, _ => { span_bug!( @@ -1559,7 +1559,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } => { let func_ty = func.ty(body, tcx); debug!("check_terminator: call, func_ty={:?}", func_ty); - let sig = match func_ty.sty { + let sig = match func_ty.kind { ty::FnDef(..) | ty::FnPtr(_) => func_ty.fn_sig(tcx), _ => { span_mirbug!(self, term, "call to non-function {:?}", func_ty); @@ -2056,7 +2056,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::Pointer(PointerCast::ClosureFnPointer(unsafety)) => { - let sig = match op.ty(body, tcx).sty { + let sig = match op.ty(body, tcx).kind { ty::Closure(def_id, substs) => { substs.closure_sig_ty(def_id, tcx).fn_sig(tcx) } @@ -2125,7 +2125,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::Pointer(PointerCast::MutToConstPointer) => { - let ty_from = match op.ty(body, tcx).sty { + let ty_from = match op.ty(body, tcx).kind { ty::RawPtr(ty::TypeAndMut { ty: ty_from, mutbl: hir::MutMutable, @@ -2140,7 +2140,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { return; } }; - let ty_to = match ty.sty { + let ty_to = match ty.kind { ty::RawPtr(ty::TypeAndMut { ty: ty_to, mutbl: hir::MutImmutable, @@ -2173,11 +2173,11 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::Misc => { - if let ty::Ref(_, mut ty_from, _) = op.ty(body, tcx).sty { + if let ty::Ref(_, mut ty_from, _) = op.ty(body, tcx).kind { let (mut ty_to, mutability) = if let ty::RawPtr(ty::TypeAndMut { ty: ty_to, mutbl, - }) = ty.sty { + }) = ty.kind { (ty_to, mutbl) } else { span_mirbug!( @@ -2192,9 +2192,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // Handle the direct cast from `&[T; N]` to `*const T` by unwrapping // any array we find. - while let ty::Array(ty_elem_from, _) = ty_from.sty { + while let ty::Array(ty_elem_from, _) = ty_from.kind { ty_from = ty_elem_from; - if let ty::Array(ty_elem_to, _) = ty_to.sty { + if let ty::Array(ty_elem_to, _) = ty_to.kind { ty_to = ty_elem_to; } else { break; @@ -2250,7 +2250,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { | Rvalue::BinaryOp(BinOp::Gt, left, right) | Rvalue::BinaryOp(BinOp::Ge, left, right) => { let ty_left = left.ty(body, tcx); - if let ty::RawPtr(_) | ty::FnPtr(_) = ty_left.sty { + if let ty::RawPtr(_) | ty::FnPtr(_) = ty_left.kind { let ty_right = right.ty(body, tcx); let common_ty = self.infcx.next_ty_var( TypeVariableOrigin { @@ -2431,7 +2431,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let base_ty = Place::ty_from(&borrowed_place.base, proj_base, body, tcx).ty; debug!("add_reborrow_constraint - base_ty = {:?}", base_ty); - match base_ty.sty { + match base_ty.kind { ty::Ref(ref_region, _, mutbl) => { constraints.outlives_constraints.push(OutlivesConstraint { sup: ref_region.to_region_vid(), diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs index 3e090aed52270..b5af97a2217e8 100644 --- a/src/librustc_mir/borrow_check/nll/universal_regions.rs +++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs @@ -486,7 +486,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let defining_ty = self.infcx .replace_free_regions_with_nll_infer_vars(FR, &defining_ty); - match defining_ty.sty { + match defining_ty.kind { ty::Closure(def_id, substs) => DefiningTy::Closure(def_id, substs), ty::Generator(def_id, substs, movability) => { DefiningTy::Generator(def_id, substs, movability) @@ -573,7 +573,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { // flattens this tuple. let (&output, tuplized_inputs) = inputs_and_output.split_last().unwrap(); assert_eq!(tuplized_inputs.len(), 1, "multiple closure inputs"); - let inputs = match tuplized_inputs[0].sty { + let inputs = match tuplized_inputs[0].kind { ty::Tuple(inputs) => inputs, _ => bug!("closure inputs not a tuple: {:?}", tuplized_inputs[0]), }; diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs index 411fa5b596765..f437c7172966b 100644 --- a/src/librustc_mir/borrow_check/place_ext.rs +++ b/src/librustc_mir/borrow_check/place_ext.rs @@ -57,7 +57,7 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { if *elem == ProjectionElem::Deref { let ty = Place::ty_from(&self.base, proj_base, body, tcx).ty; - if let ty::RawPtr(..) | ty::Ref(_, _, hir::MutImmutable) = ty.sty { + if let ty::RawPtr(..) | ty::Ref(_, _, hir::MutImmutable) = ty.kind { // For both derefs of raw pointers and `&T` // references, the original path is `Copy` and // therefore not significant. In particular, diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index dafa0b6631fe2..9dd3e119c217a 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -231,7 +231,7 @@ fn place_components_conflict<'tcx>( let proj_base = &borrow_place.projection[..access_place.projection.len() + i]; let base_ty = Place::ty_from(borrow_base, proj_base, body, tcx).ty; - match (elem, &base_ty.sty, access) { + match (elem, &base_ty.kind, access) { (_, _, Shallow(Some(ArtificialField::ArrayLength))) | (_, _, Shallow(Some(ArtificialField::ShallowBorrow))) => { // The array length is like additional fields on the @@ -349,7 +349,7 @@ fn place_base_conflict<'tcx>( }, (StaticKind::Promoted(promoted_1, _), StaticKind::Promoted(promoted_2, _)) => { if promoted_1 == promoted_2 { - if let ty::Array(_, len) = s1.ty.sty { + if let ty::Array(_, len) = s1.ty.kind { if let Some(0) = len.try_eval_usize(tcx, param_env) { // Ignore conflicts with promoted [T; 0]. debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED"); @@ -404,7 +404,7 @@ fn place_projection_conflict<'tcx>( Overlap::EqualOrDisjoint } else { let ty = Place::ty_from(pi1_base, pi1_proj_base, body, tcx).ty; - match ty.sty { + match ty.kind { ty::Adt(def, _) if def.is_union() => { // Different fields of a union, we are basically stuck. debug!("place_element_conflict: STUCK-UNION"); diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index 0a268ec134023..a46a1cc5647a9 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -144,7 +144,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> { // reference. let ty = Place::ty_from(cursor.base, proj_base, self.body, self.tcx).ty; - match ty.sty { + match ty.kind { ty::RawPtr(_) | ty::Ref( _, /*rgn*/ diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 30d53502b11ff..8a6bc5a2a764e 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -196,7 +196,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { exit_block.unit() } ExprKind::Call { ty, fun, args, from_hir_call } => { - let intrinsic = match ty.sty { + let intrinsic = match ty.kind { ty::FnDef(def_id, _) => { let f = ty.fn_sig(this.hir.tcx()); if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic { diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index 8d049b53988a9..224b1a2b4efee 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -109,7 +109,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } PatternKind::Range(PatternRange { lo, hi, end }) => { - let (range, bias) = match lo.ty.sty { + let (range, bias) = match lo.ty.kind { ty::Char => { (Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32))), 0) } diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index d5890d00ea80f..03f9e4ccc970b 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -229,7 +229,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { TestKind::SwitchInt { switch_ty, ref options, indices: _ } => { let target_blocks = make_target_blocks(self); - let terminator = if switch_ty.sty == ty::Bool { + let terminator = if switch_ty.kind == ty::Bool { assert!(options.len() > 0 && options.len() <= 2); if let [first_bb, second_bb] = *target_blocks { let (true_bb, false_bb) = match options[0] { @@ -400,8 +400,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // We want to do this even when the scrutinee is a reference to an // array, so we can call `<[u8]>::eq` rather than having to find an // `<[u8; N]>::eq`. - let unsize = |ty: Ty<'tcx>| match ty.sty { - ty::Ref(region, rty, _) => match rty.sty { + let unsize = |ty: Ty<'tcx>| match ty.kind { + ty::Ref(region, rty, _) => match rty.kind { ty::Array(inner_ty, n) => Some((region, inner_ty, n)), _ => None, }, @@ -438,7 +438,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }, } - let deref_ty = match ty.sty { + let deref_ty = match ty.kind { ty::Ref(_, deref_ty, _) => deref_ty, _ => bug!("non_scalar_compare called on non-reference type: {}", ty), }; diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 647d7515fe98d..b0572df9d0853 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -73,7 +73,7 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> { let ty = tcx.type_of(fn_def_id); let mut abi = fn_sig.abi; - let implicit_argument = match ty.sty { + let implicit_argument = match ty.kind { ty::Closure(..) => { // HACK(eddyb) Avoid having RustCall on closures, // as it adds unnecessary (and wrong) auto-tupling. @@ -127,7 +127,7 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> { let arguments = implicit_argument.into_iter().chain(explicit_arguments); let (yield_ty, return_ty) = if body.generator_kind.is_some() { - let gen_sig = match ty.sty { + let gen_sig = match ty.kind { ty::Generator(gen_def_id, gen_substs, ..) => gen_substs.sig(gen_def_id, tcx), _ => @@ -178,7 +178,7 @@ fn liberated_closure_env_ty( ) -> Ty<'_> { let closure_ty = tcx.body_tables(body_id).node_type(closure_expr_id); - let (closure_def_id, closure_substs) = match closure_ty.sty { + let (closure_def_id, closure_substs) = match closure_ty.kind { ty::Closure(closure_def_id, closure_substs) => (closure_def_id, closure_substs), _ => bug!("closure expr does not have closure type: {:?}", closure_ty) }; diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 435159827e6c3..d1e00253a98de 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -63,8 +63,8 @@ fn op_to_const<'tcx>( // `Undef` situation. let try_as_immediate = match op.layout.abi { layout::Abi::Scalar(..) => true, - layout::Abi::ScalarPair(..) => match op.layout.ty.sty { - ty::Ref(_, inner, _) => match inner.sty { + layout::Abi::ScalarPair(..) => match op.layout.ty.kind { + ty::Ref(_, inner, _) => match inner.kind { ty::Slice(elem) => elem == ecx.tcx.types.u8, ty::Str => true, _ => false, diff --git a/src/librustc_mir/dataflow/drop_flag_effects.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs index 444cc008ae785..51b717b69e9c1 100644 --- a/src/librustc_mir/dataflow/drop_flag_effects.rs +++ b/src/librustc_mir/dataflow/drop_flag_effects.rs @@ -50,7 +50,7 @@ fn place_contents_drop_state_cannot_differ<'tcx>( place: &mir::Place<'tcx>, ) -> bool { let ty = place.ty(body, tcx).ty; - match ty.sty { + match ty.kind { ty::Array(..) => { debug!("place_contents_drop_state_cannot_differ place: {:?} ty: {:?} => false", place, ty); diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 698c50166270a..d9119253cae5f 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -106,7 +106,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { let body = self.builder.body; let tcx = self.builder.tcx; let place_ty = Place::ty_from(&place.base, proj_base, body, tcx).ty; - match place_ty.sty { + match place_ty.kind { ty::Ref(..) | ty::RawPtr(..) => { let proj = &place.projection[..i+1]; return Err(MoveError::cannot_move_out_of( @@ -438,7 +438,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { // of the union so it is marked as initialized again. if let [proj_base @ .., ProjectionElem::Field(_, _)] = place.projection { if let ty::Adt(def, _) = - Place::ty_from(place.base, proj_base, self.builder.body, self.builder.tcx).ty.sty + Place::ty_from(place.base, proj_base, self.builder.body, self.builder.tcx).ty.kind { if def.is_union() { place = PlaceRef { base: place.base, projection: proj_base } diff --git a/src/librustc_mir/hair/constant.rs b/src/librustc_mir/hair/constant.rs index bc01e3ee95b97..956716f8ceaf7 100644 --- a/src/librustc_mir/hair/constant.rs +++ b/src/librustc_mir/hair/constant.rs @@ -49,7 +49,7 @@ crate fn lit_to_const<'tcx>( parse_float(n, fty, neg).map_err(|_| LitToConstError::UnparseableFloat)? } LitKind::FloatUnsuffixed(n) => { - let fty = match ty.sty { + let fty = match ty.kind { ty::Float(fty) => fty, _ => bug!() }; diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index a33d7207ed4e1..d57b68c48ee58 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -442,7 +442,7 @@ fn make_mirror_unadjusted<'a, 'tcx>( } hir::ExprKind::Struct(ref qpath, ref fields, ref base) => { - match expr_ty.sty { + match expr_ty.kind { ty::Adt(adt, substs) => { match adt.adt_kind() { AdtKind::Struct | AdtKind::Union => { @@ -505,7 +505,7 @@ fn make_mirror_unadjusted<'a, 'tcx>( hir::ExprKind::Closure(..) => { let closure_ty = cx.tables().expr_ty(expr); - let (def_id, substs, movability) = match closure_ty.sty { + let (def_id, substs, movability) = match closure_ty.kind { ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs), None), ty::Generator(def_id, substs, movability) => { (def_id, UpvarSubsts::Generator(substs), Some(movability)) @@ -938,7 +938,7 @@ fn convert_path_expr<'a, 'tcx>( let user_provided_type = user_provided_types.get(expr.hir_id).map(|u_ty| *u_ty); debug!("convert_path_expr: user_provided_type={:?}", user_provided_type); let ty = cx.tables().node_type(expr.hir_id); - match ty.sty { + match ty.kind { // A unit struct/variant which is used as a value. // We return a completely different ExprKind here to account for this special case. ty::Adt(adt_def, substs) => { @@ -1001,7 +1001,7 @@ fn convert_var( }); let region = cx.tcx.mk_region(region); - let self_expr = if let ty::Closure(_, closure_substs) = closure_ty.sty { + let self_expr = if let ty::Closure(_, closure_substs) = closure_ty.kind { match cx.infcx.closure_kind(closure_def_id, closure_substs).unwrap() { ty::ClosureKind::Fn => { let ref_closure_ty = cx.tcx.mk_ref(region, @@ -1147,7 +1147,7 @@ fn overloaded_place<'a, 'tcx>( // Reconstruct the output assuming it's a reference with the // same region and mutability as the receiver. This holds for // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`. - let (region, mutbl) = match recv_ty.sty { + let (region, mutbl) = match recv_ty.kind { ty::Ref(region, _, mutbl) => (region, mutbl), _ => span_bug!(expr.span, "overloaded_place: receiver is not a reference"), }; diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index a6d955f336910..e570ace8df1d2 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -213,7 +213,7 @@ impl LiteralExpander<'tcx> { crty: Ty<'tcx>, ) -> ConstValue<'tcx> { debug!("fold_const_value_deref {:?} {:?} {:?}", val, rty, crty); - match (val, &crty.sty, &rty.sty) { + match (val, &crty.kind, &rty.kind) { // the easy case, deref a reference (ConstValue::Scalar(Scalar::Ptr(p)), x, y) if x == y => { let alloc = self.tcx.alloc_map.lock().unwrap_memory(p.alloc_id); @@ -244,13 +244,13 @@ impl LiteralExpander<'tcx> { impl PatternFolder<'tcx> for LiteralExpander<'tcx> { fn fold_pattern(&mut self, pat: &Pattern<'tcx>) -> Pattern<'tcx> { - debug!("fold_pattern {:?} {:?} {:?}", pat, pat.ty.sty, pat.kind); - match (&pat.ty.sty, &*pat.kind) { + debug!("fold_pattern {:?} {:?} {:?}", pat, pat.ty.kind, pat.kind); + match (&pat.ty.kind, &*pat.kind) { ( &ty::Ref(_, rty, _), &PatternKind::Constant { value: Const { val, - ty: ty::TyS { sty: ty::Ref(_, crty, _), .. }, + ty: ty::TyS { kind: ty::Ref(_, crty, _), .. }, } }, ) => { Pattern { @@ -406,14 +406,14 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { } fn is_non_exhaustive_enum(&self, ty: Ty<'tcx>) -> bool { - match ty.sty { + match ty.kind { ty::Adt(adt_def, ..) => adt_def.is_variant_list_non_exhaustive(), _ => false, } } fn is_local(&self, ty: Ty<'tcx>) -> bool { - match ty.sty { + match ty.kind { ty::Adt(adt_def, ..) => adt_def.did.is_local(), _ => false, } @@ -565,7 +565,7 @@ impl<'tcx> Witness<'tcx> { let len = self.0.len() as u64; let mut pats = self.0.drain((len - arity) as usize..).rev(); - match ty.sty { + match ty.kind { ty::Adt(..) | ty::Tuple(..) => { let pats = pats.enumerate().map(|(i, p)| { @@ -575,7 +575,7 @@ impl<'tcx> Witness<'tcx> { } }).collect(); - if let ty::Adt(adt, substs) = ty.sty { + if let ty::Adt(adt, substs) = ty.kind { if adt.is_enum() { PatternKind::Variant { adt_def: adt, @@ -639,7 +639,7 @@ fn all_constructors<'a, 'tcx>( pcx: PatternContext<'tcx>, ) -> Vec> { debug!("all_constructors({:?})", pcx.ty); - let ctors = match pcx.ty.sty { + let ctors = match pcx.ty.kind { ty::Bool => { [true, false].iter().map(|&b| { ConstantValue(ty::Const::from_bool(cx.tcx, b)) @@ -785,7 +785,7 @@ where match *row.kind { PatternKind::Constant { value } => { // extract the length of an array/slice from a constant - match (value.val, &value.ty.sty) { + match (value.val, &value.ty.kind) { (_, ty::Array(_, n)) => max_fixed_len = cmp::max( max_fixed_len, n.eval_usize(cx.tcx, cx.param_env), @@ -837,7 +837,7 @@ impl<'tcx> IntRange<'tcx> { // Floating-point ranges are permitted and we don't want // to consider them when constructing integer ranges. fn is_integral(ty: Ty<'_>) -> bool { - match ty.sty { + match ty.kind { ty::Char | ty::Int(_) | ty::Uint(_) => true, _ => false, } @@ -896,7 +896,7 @@ impl<'tcx> IntRange<'tcx> { // The return value of `signed_bias` should be XORed with an endpoint to encode/decode it. fn signed_bias(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> u128 { - match ty.sty { + match ty.kind { ty::Int(ity) => { let bits = Integer::from_attr(&tcx, SignedInt(ity)).size().bits() as u128; 1u128 << (bits - 1) @@ -1345,7 +1345,7 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>, lo.ty, end, )]), - PatternKind::Array { .. } => match pcx.ty.sty { + PatternKind::Array { .. } => match pcx.ty.kind { ty::Array(_, length) => Some(vec![ Slice(length.eval_usize(cx.tcx, cx.param_env)) ]), @@ -1372,7 +1372,7 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>, /// A struct pattern's arity is the number of fields it contains, etc. fn constructor_arity(cx: &MatchCheckCtxt<'a, 'tcx>, ctor: &Constructor<'tcx>, ty: Ty<'tcx>) -> u64 { debug!("constructor_arity({:#?}, {:?})", ctor, ty); - match ty.sty { + match ty.kind { ty::Tuple(ref fs) => fs.len() as u64, ty::Slice(..) | ty::Array(..) => match *ctor { Slice(length) => length, @@ -1397,7 +1397,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx>( ty: Ty<'tcx>, ) -> Vec> { debug!("constructor_sub_pattern_tys({:#?}, {:?})", ctor, ty); - match ty.sty { + match ty.kind { ty::Tuple(ref fs) => fs.into_iter().map(|t| t.expect_ty()).collect(), ty::Slice(ty) | ty::Array(ty, _) => match *ctor { Slice(length) => (0..length).map(|_| ty).collect(), @@ -1415,7 +1415,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx>( || field.vis.is_accessible_from(cx.module, cx.tcx); if is_visible { let ty = field.ty(cx.tcx, substs); - match ty.sty { + match ty.kind { // If the field type returned is an array of an unknown // size return an TyErr. ty::Array(_, len) @@ -1451,7 +1451,7 @@ fn slice_pat_covered_by_const<'tcx>( suffix: &[Pattern<'tcx>], param_env: ty::ParamEnv<'tcx>, ) -> Result { - let data: &[u8] = match (const_val.val, &const_val.ty.sty) { + let data: &[u8] = match (const_val.val, &const_val.ty.kind) { (ConstValue::ByRef { offset, alloc, .. }, ty::Array(t, n)) => { assert_eq!(*t, tcx.types.u8); let n = n.eval_usize(tcx, param_env); @@ -1503,7 +1503,7 @@ fn should_treat_range_exhaustively(tcx: TyCtxt<'tcx>, ctor: &Constructor<'tcx>) ConstantRange(_, _, ty, _) => ty, _ => return false, }; - if let ty::Char | ty::Int(_) | ty::Uint(_) = ty.sty { + if let ty::Char | ty::Int(_) | ty::Uint(_) = ty.kind { !ty.is_ptr_sized_integral() || tcx.features().precise_pointer_size_matching } else { false @@ -1775,7 +1775,7 @@ fn specialize<'p, 'a: 'p, 'tcx>( // necessarily point to memory, they are usually just integers. The only time // they should be pointing to memory is when they are subslices of nonzero // slices - let (alloc, offset, n, ty) = match value.ty.sty { + let (alloc, offset, n, ty) = match value.ty.kind { ty::Array(t, n) => { match value.val { ConstValue::ByRef { offset, alloc, .. } => ( diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 161c58a175579..57e0a48ca89e4 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -191,7 +191,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { let scrutinee_is_uninhabited = if self.tcx.features().exhaustive_patterns { self.tcx.is_ty_uninhabited_from(module, pat_ty) } else { - match pat_ty.sty { + match pat_ty.kind { ty::Never => true, ty::Adt(def, _) => { def_span = self.tcx.hir().span_if_local(def.did); @@ -298,7 +298,7 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_>, pat: &Pa return true; } let pat_ty = cx.tables.pat_ty(p); - if let ty::Adt(edef, _) = pat_ty.sty { + if let ty::Adt(edef, _) = pat_ty.kind { if edef.is_enum() && edef.variants.iter().any(|variant| { variant.ident == ident && variant.ctor_kind == CtorKind::Const }) { @@ -492,7 +492,7 @@ fn adt_defined_here( witnesses: &[Pattern<'_>], ) { let ty = ty.peel_refs(); - if let ty::Adt(def, _) = ty.sty { + if let ty::Adt(def, _) = ty.kind { if let Some(sp) = cx.tcx.hir().span_if_local(def.did) { err.span_label(sp, format!("`{}` defined here", ty)); } @@ -507,7 +507,7 @@ fn adt_defined_here( fn maybe_point_at_variant(ty: Ty<'_>, patterns: &[Pattern<'_>]) -> Vec { let mut covered = vec![]; - if let ty::Adt(def, _) = ty.sty { + if let ty::Adt(def, _) = ty.kind { // Don't point at variants that have already been covered due to other patterns to avoid // visual clutter. for pattern in patterns { diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 4aaa5e8ee259a..162251bf76e7f 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -231,7 +231,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { PatternKind::Variant { adt_def, variant_index, .. } => { Some(&adt_def.variants[variant_index]) } - _ => if let ty::Adt(adt, _) = self.ty.sty { + _ => if let ty::Adt(adt, _) = self.ty.kind { if !adt.is_enum() { Some(&adt.variants[VariantIdx::new(0)]) } else { @@ -295,7 +295,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { Ok(()) } PatternKind::Deref { ref subpattern } => { - match self.ty.sty { + match self.ty.kind { ty::Adt(def, _) if def.is_box() => write!(f, "box ")?, ty::Ref(_, _, mutbl) => { write!(f, "&")?; @@ -548,7 +548,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } PatKind::Slice(ref prefix, ref slice, ref suffix) => { - match ty.sty { + match ty.kind { ty::Ref(_, ty, _) => PatternKind::Deref { subpattern: Pattern { @@ -573,7 +573,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } PatKind::Tuple(ref subpatterns, ddpos) => { - match ty.sty { + match ty.kind { ty::Tuple(ref tys) => { let subpatterns = subpatterns.iter() @@ -595,7 +595,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { PatKind::Binding(_, id, ident, ref sub) => { let var_ty = self.tables.node_type(pat.hir_id); - if let ty::Error = var_ty.sty { + if let ty::Error = var_ty.kind { // Avoid ICE return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) }; }; @@ -617,7 +617,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { // A ref x pattern is the same node used for x, and as such it has // x's type, which is &T, where we want T (the type being matched). if let ty::BindByReference(_) = bm { - if let ty::Ref(_, rty, _) = ty.sty { + if let ty::Ref(_, rty, _) = ty.kind { ty = rty; } else { bug!("`ref {}` has wrong type {}", ident, ty); @@ -636,7 +636,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { PatKind::TupleStruct(ref qpath, ref subpatterns, ddpos) => { let res = self.tables.qpath_res(qpath, pat.hir_id); - let adt_def = match ty.sty { + let adt_def = match ty.kind { ty::Adt(adt_def, _) => adt_def, ty::Error => { // Avoid ICE (#50585) return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) }; @@ -747,7 +747,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { let (prefix, slice, suffix) = self.flatten_nested_slice_patterns(prefix, slice, suffix); - match ty.sty { + match ty.kind { ty::Slice(..) => { // matching a slice or fixed-length array PatternKind::Slice { prefix: prefix, slice: slice, suffix: suffix } @@ -787,7 +787,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { let enum_id = self.tcx.parent(variant_id).unwrap(); let adt_def = self.tcx.adt_def(enum_id); if adt_def.is_enum() { - let substs = match ty.sty { + let substs = match ty.kind { ty::Adt(_, substs) | ty::FnDef(_, substs) => substs, ty::Error => { // Avoid ICE (#50585) @@ -1077,7 +1077,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { }; - let kind = match cv.ty.sty { + let kind = match cv.ty.kind { ty::Float(_) => { self.tcx.lint_hir( ::rustc::lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, @@ -1109,7 +1109,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { PatternKind::Wild } // keep old code until future-compat upgraded to errors. - ty::Ref(_, ty::TyS { sty: ty::Adt(adt_def, _), .. }, _) + ty::Ref(_, ty::TyS { kind: ty::Adt(adt_def, _), .. }, _) if !self.tcx.has_attr(adt_def.did, sym::structural_match) => { // HACK(estebank): Side-step ICE #53708, but anything other than erroring here // would be wrong. Returnging `PatternKind::Wild` is not technically correct. @@ -1224,7 +1224,7 @@ fn search_for_adt_without_structural_match<'tcx>(tcx: TyCtxt<'tcx>, fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { debug!("Search visiting ty: {:?}", ty); - let (adt_def, substs) = match ty.sty { + let (adt_def, substs) = match ty.kind { ty::Adt(adt_def, substs) => (adt_def, substs), ty::RawPtr(..) => { // `#[structural_match]` ignores substructure of @@ -1501,7 +1501,7 @@ pub fn compare_const_vals<'tcx>( if let (Some(a), Some(b)) = (a_bits, b_bits) { use ::rustc_apfloat::Float; - return match ty.sty { + return match ty.kind { ty::Float(ast::FloatTy::F32) => { let l = ::rustc_apfloat::ieee::Single::from_bits(a); let r = ::rustc_apfloat::ieee::Single::from_bits(b); @@ -1524,7 +1524,7 @@ pub fn compare_const_vals<'tcx>( } } - if let ty::Str = ty.sty { + if let ty::Str = ty.kind { match (a.val, b.val) { ( ConstValue::Slice { data: alloc_a, start: offset_a, end: end_a }, diff --git a/src/librustc_mir/hair/util.rs b/src/librustc_mir/hair/util.rs index 4e014855df5e0..d63541f7a3f56 100644 --- a/src/librustc_mir/hair/util.rs +++ b/src/librustc_mir/hair/util.rs @@ -17,7 +17,7 @@ crate trait UserAnnotatedTyHelpers<'tcx> { let mut user_ty = *user_provided_types.get(hir_id)?; debug!("user_subts_applied_to_ty_of_hir_id: user_ty={:?}", user_ty); let ty = self.tables().node_type(hir_id); - match ty.sty { + match ty.kind { ty::Adt(adt_def, ..) => { if let UserType::TypeOf(ref mut did, _) = &mut user_ty.value { *did = adt_def.did; diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 2797766f2171e..d120412c901a6 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -34,7 +34,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Pointer(PointerCast::ReifyFnPointer) => { // The src operand does not matter, just its type - match src.layout.ty.sty { + match src.layout.ty.kind { ty::FnDef(def_id, substs) => { // All reifications must be monomorphic, bail out otherwise. if src.layout.ty.needs_subst() { @@ -54,7 +54,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Pointer(PointerCast::UnsafeFnPointer) => { let src = self.read_immediate(src)?; - match dest.layout.ty.sty { + match dest.layout.ty.kind { ty::FnPtr(_) => { // No change to value self.write_immediate(*src, dest)?; @@ -65,7 +65,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Pointer(PointerCast::ClosureFnPointer(_)) => { // The src operand does not matter, just its type - match src.layout.ty.sty { + match src.layout.ty.kind { ty::Closure(def_id, substs) => { // All reifications must be monomorphic, bail out otherwise. if src.layout.ty.needs_subst() { @@ -97,7 +97,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { use rustc::ty::TyKind::*; trace!("Casting {:?}: {:?} to {:?}", *src, src.layout.ty, dest_layout.ty); - match src.layout.ty.sty { + match src.layout.ty.kind { // Floating point Float(FloatTy::F32) => return Ok(self.cast_from_float(src.to_scalar()?.to_f32()?, dest_layout.ty)?.into()), @@ -176,7 +176,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; trace!("cast_from_int: {}, {}, {}", v, src_layout.ty, dest_layout.ty); use rustc::ty::TyKind::*; - match dest_layout.ty.sty { + match dest_layout.ty.kind { Int(_) | Uint(_) | RawPtr(_) => { let v = self.truncate(v, dest_layout); Ok(Scalar::from_uint(v, dest_layout.size)) @@ -214,7 +214,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { where F: Float + Into> + FloatConvert + FloatConvert { use rustc::ty::TyKind::*; - match dest_ty.sty { + match dest_ty.kind { // float -> uint Uint(t) => { let width = t.bit_width().unwrap_or_else(|| self.pointer_size().bits() as usize); @@ -251,7 +251,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let (src_pointee_ty, dest_pointee_ty) = self.tcx.struct_lockstep_tails_erasing_lifetimes(source_ty, dest_ty, self.param_env); - match (&src_pointee_ty.sty, &dest_pointee_ty.sty) { + match (&src_pointee_ty.kind, &dest_pointee_ty.kind) { (&ty::Array(_, length), &ty::Slice(_)) => { let ptr = self.read_immediate(src)?.to_scalar_ptr()?; // u64 cast is from usize to u64, which is always good @@ -287,7 +287,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { dest: PlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx> { trace!("Unsizing {:?} into {:?}", src, dest); - match (&src.layout.ty.sty, &dest.layout.ty.sty) { + match (&src.layout.ty.kind, &dest.layout.ty.kind) { (&ty::Ref(_, s, _), &ty::Ref(_, d, _)) | (&ty::Ref(_, s, _), &ty::RawPtr(TypeAndMut { ty: d, .. })) | (&ty::RawPtr(TypeAndMut { ty: s, .. }), diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 78996ed6939d8..fdf85260c3d96 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -387,7 +387,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if !layout.is_unsized() { return Ok(Some((layout.size, layout.align.abi))); } - match layout.ty.sty { + match layout.ty.kind { ty::Adt(..) | ty::Tuple(..) => { // First get the size of all statically known fields. // Don't use type_of::sizing_type_of because that expects t to be sized, diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 95647ce642c5b..ec06b6298e112 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -192,13 +192,13 @@ for // Handle Reference types, as these are the only relocations supported by const eval. // Raw pointers (and boxes) are handled by the `leftover_relocations` logic. let ty = mplace.layout.ty; - if let ty::Ref(_, referenced_ty, mutability) = ty.sty { + if let ty::Ref(_, referenced_ty, mutability) = ty.kind { let value = self.ecx.read_immediate(mplace.into())?; // Handle trait object vtables if let Ok(meta) = value.to_meta() { if let ty::Dynamic(..) = self.ecx.tcx.struct_tail_erasing_lifetimes( - referenced_ty, self.ecx.param_env).sty + referenced_ty, self.ecx.param_env).kind { if let Ok(vtable) = meta.unwrap().to_ptr() { // explitly choose `Immutable` here, since vtables are immutable, even @@ -228,7 +228,7 @@ for // we statically prevent `&mut T` via `const_qualif` and double check this here (InternMode::ConstBase, hir::Mutability::MutMutable) | (InternMode::Const, hir::Mutability::MutMutable) => { - match referenced_ty.sty { + match referenced_ty.kind { ty::Array(_, n) if n.eval_usize(self.ecx.tcx.tcx, self.ecx.param_env) == 0 => {} ty::Slice(_) diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs index 1e765a4ed982c..a6b3b4e0ff67d 100644 --- a/src/librustc_mir/interpret/intrinsics/type_name.rs +++ b/src/librustc_mir/interpret/intrinsics/type_name.rs @@ -32,7 +32,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { } fn print_type(mut self, ty: Ty<'tcx>) -> Result { - match ty.sty { + match ty.kind { // Types without identity. | ty::Bool | ty::Char diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index dd214c4a031f7..ba35623ab12c7 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -653,7 +653,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { bits_discr }; // Make sure we catch invalid discriminants - let index = match &rval.layout.ty.sty { + let index = match &rval.layout.ty.kind { ty::Adt(adt, _) => adt .discriminants(self.tcx.tcx) .find(|(_, var)| var.val == real_discr), diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index 470cc9346ee21..176b084f22587 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -274,7 +274,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { trace!("Running binary op {:?}: {:?} ({:?}), {:?} ({:?})", bin_op, *left, left.layout.ty, *right, right.layout.ty); - match left.layout.ty.sty { + match left.layout.ty.kind { ty::Char => { assert_eq!(left.layout.ty, right.layout.ty); let left = left.to_scalar()?; @@ -348,7 +348,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let val = val.to_scalar()?; trace!("Running unary op {:?}: {:?} ({:?})", un_op, val, layout.ty); - match layout.ty.sty { + match layout.ty.kind { ty::Bool => { let val = val.to_bool()?; let res = match un_op { diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index c3660fb7a2e28..2f1b35757fe9c 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -193,7 +193,7 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> { pub(super) fn len(self, cx: &impl HasDataLayout) -> InterpResult<'tcx, u64> { if self.layout.is_unsized() { // We need to consult `meta` metadata - match self.layout.ty.sty { + match self.layout.ty.kind { ty::Slice(..) | ty::Str => return self.mplace.meta.unwrap().to_usize(cx), _ => bug!("len not supported on unsized type {:?}", self.layout.ty), @@ -210,7 +210,7 @@ impl<'tcx, Tag> MPlaceTy<'tcx, Tag> { #[inline] pub(super) fn vtable(self) -> Scalar { - match self.layout.ty.sty { + match self.layout.ty.kind { ty::Dynamic(..) => self.mplace.meta.unwrap(), _ => bug!("vtable not supported on type {:?}", self.layout.ty), } @@ -459,7 +459,7 @@ where // Compute meta and new layout let inner_len = len - to - from; - let (meta, ty) = match base.layout.ty.sty { + let (meta, ty) = match base.layout.ty.kind { // It is not nice to match on the type, but that seems to be the only way to // implement this. ty::Array(inner, _) => diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 8310ef02f9669..e6598bc0ffbef 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -75,7 +75,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; let func = self.eval_operand(func, None)?; - let (fn_val, abi) = match func.layout.ty.sty { + let (fn_val, abi) = match func.layout.ty.kind { ty::FnPtr(sig) => { let caller_abi = sig.abi(); let fn_ptr = self.read_scalar(func)?.not_undef()?; @@ -275,7 +275,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { { let callee_abi = { let instance_ty = instance.ty(*self.tcx); - match instance_ty.sty { + match instance_ty.kind { ty::FnDef(..) => instance_ty.fn_sig(*self.tcx).abi(), ty::Closure(..) => Abi::RustCall, @@ -482,7 +482,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // implementation fail -- a problem shared by rustc. let place = self.force_allocation(place)?; - let (instance, place) = match place.layout.ty.sty { + let (instance, place) = match place.layout.ty.kind { ty::Dynamic(..) => { // Dropping a trait object. self.unpack_dyn_trait(place)? diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 3e14ba3efcc58..e6fa833c7b25b 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -188,7 +188,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M layout: TyLayout<'tcx>, field: usize, ) -> PathElem { - match layout.ty.sty { + match layout.ty.kind { // generators and closures. ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => { let mut name = None; @@ -263,7 +263,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M pointee: TyLayout<'tcx>, ) -> InterpResult<'tcx> { let tail = self.ecx.tcx.struct_tail_erasing_lifetimes(pointee.ty, self.ecx.param_env); - match tail.sty { + match tail.kind { ty::Dynamic(..) => { let vtable = meta.unwrap(); try_validation!( @@ -327,7 +327,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> variant_id: VariantIdx, new_op: OpTy<'tcx, M::PointerTag> ) -> InterpResult<'tcx> { - let name = match old_op.layout.ty.sty { + let name = match old_op.layout.ty.kind { ty::Adt(adt, _) => PathElem::Variant(adt.variants[variant_id].ident.name), // Generators also have variants ty::Generator(..) => PathElem::GeneratorState(variant_id), @@ -362,7 +362,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> let value = self.ecx.read_immediate(value)?; // Go over all the primitive types let ty = value.layout.ty; - match ty.sty { + match ty.kind { ty::Bool => { let value = value.to_scalar_or_undef(); try_validation!(value.to_bool(), @@ -581,7 +581,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> op: OpTy<'tcx, M::PointerTag>, fields: impl Iterator>, ) -> InterpResult<'tcx> { - match op.layout.ty.sty { + match op.layout.ty.kind { ty::Str => { let mplace = op.assert_mem_place(); // strings are never immediate try_validation!(self.ecx.read_str(mplace), @@ -590,7 +590,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> ty::Array(tys, ..) | ty::Slice(tys) if { // This optimization applies only for integer and floating point types // (i.e., types that can hold arbitrary bytes). - match tys.sty { + match tys.kind { ty::Int(..) | ty::Uint(..) | ty::Float(..) => true, _ => false, } diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs index 91fbd307db121..427f94f4fbb02 100644 --- a/src/librustc_mir/interpret/visitor.rs +++ b/src/librustc_mir/interpret/visitor.rs @@ -239,7 +239,7 @@ macro_rules! make_value_visitor { // Even for single variants, we might be able to get a more refined type: // If it is a trait object, switch to the actual type that was used to create it. - match v.layout().ty.sty { + match v.layout().ty.kind { ty::Dynamic(..) => { // immediate trait objects are not a thing let dest = v.to_op(self.ecx())?.assert_mem_place(); diff --git a/src/librustc_mir/lints.rs b/src/librustc_mir/lints.rs index 8c815a51b5d65..4f978051eaccd 100644 --- a/src/librustc_mir/lints.rs +++ b/src/librustc_mir/lints.rs @@ -86,7 +86,7 @@ fn check_fn_for_unconditional_recursion( TerminatorKind::Call { ref func, .. } => { let func_ty = func.ty(body, tcx); - if let ty::FnDef(fn_def_id, substs) = func_ty.sty { + if let ty::FnDef(fn_def_id, substs) = func_ty.kind { let (call_fn_id, call_substs) = if let Some(instance) = Instance::resolve(tcx, param_env, diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 1f7efebfda819..d7a837e7ede66 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -578,7 +578,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { ty::ParamEnv::reveal_all(), &source_ty, ); - match source_ty.sty { + match source_ty.kind { ty::Closure(def_id, substs) => { let instance = Instance::resolve_closure( self.tcx, def_id, substs, ty::ClosureKind::FnOnce); @@ -712,7 +712,7 @@ fn visit_fn_use<'tcx>( is_direct_call: bool, output: &mut Vec>, ) { - if let ty::FnDef(def_id, substs) = ty.sty { + if let ty::FnDef(def_id, substs) = ty.kind { let instance = ty::Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, @@ -874,7 +874,7 @@ fn find_vtable_types_for_unsizing<'tcx>( return false; } let tail = tcx.struct_tail_erasing_lifetimes(ty, param_env); - match tail.sty { + match tail.kind { ty::Foreign(..) => false, ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, _ => bug!("unexpected unsized tail: {:?}", tail), @@ -887,7 +887,7 @@ fn find_vtable_types_for_unsizing<'tcx>( } }; - match (&source_ty.sty, &target_ty.sty) { + match (&source_ty.kind, &target_ty.kind) { (&ty::Ref(_, a, _), &ty::Ref(_, b, _)) | (&ty::Ref(_, a, _), @@ -945,7 +945,7 @@ fn create_mono_items_for_vtable_methods<'tcx>( assert!(!trait_ty.needs_subst() && !trait_ty.has_escaping_bound_vars() && !impl_ty.needs_subst() && !impl_ty.has_escaping_bound_vars()); - if let ty::Dynamic(ref trait_ty, ..) = trait_ty.sty { + if let ty::Dynamic(ref trait_ty, ..) = trait_ty.kind { if let Some(principal) = trait_ty.principal() { let poly_trait_ref = principal.with_self_ty(tcx, impl_ty); assert!(!poly_trait_ref.has_escaping_bound_vars()); diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 6daca5e261431..f5eb07882fe32 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -167,7 +167,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) debug!("build_drop_shim(def_id={:?}, ty={:?})", def_id, ty); // Check if this is a generator, if so, return the drop glue for it - if let Some(&ty::TyS { sty: ty::Generator(gen_def_id, substs, _), .. }) = ty { + if let Some(&ty::TyS { kind: ty::Generator(gen_def_id, substs, _), .. }) = ty { let body = &**tcx.optimized_mir(gen_def_id).generator_drop.as_ref().unwrap(); return body.subst(tcx, substs.substs); } @@ -311,7 +311,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) - let dest = Place::return_place(); let src = Place::from(Local::new(1+0)).deref(); - match self_ty.sty { + match self_ty.kind { _ if is_copy => builder.copy_shim(), ty::Array(ty, len) => { let len = len.eval_usize(tcx, param_env); @@ -857,7 +857,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &Body<'_> { .expect("LBR in ADT constructor signature"); let sig = tcx.normalize_erasing_regions(param_env, sig); - let (adt_def, substs) = match sig.output().sty { + let (adt_def, substs) = match sig.output().kind { ty::Adt(adt_def, substs) => (adt_def, substs), _ => bug!("unexpected type for ADT ctor {:?}", sig.output()) }; diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index 833c8b1646bb6..b56a1b263fd6a 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -37,7 +37,7 @@ fn is_stable( /// Determine whether this type may be a reference (or box), and thus needs retagging. fn may_be_reference<'tcx>(ty: Ty<'tcx>) -> bool { - match ty.sty { + match ty.kind { // Primitive types that are not references ty::Bool | ty::Char | ty::Float(_) | ty::Int(_) | ty::Uint(_) | diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 61e32ca8de522..faec8c7cbe400 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -182,7 +182,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { // result of a comparison of addresses would differ between runtime and compile-time. Rvalue::BinaryOp(_, ref lhs, _) if self.const_context && self.tcx.features().const_compare_raw_pointers => { - if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).sty { + if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind { self.register_violations(&[UnsafetyViolation { source_info: self.source_info, description: InternedString::intern("pointer operation"), @@ -274,7 +274,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { } } let base_ty = Place::ty_from(&place.base, proj_base, self.body, self.tcx).ty; - match base_ty.sty { + match base_ty.kind { ty::RawPtr(..) => { self.require_unsafe("dereference of raw pointer", "raw pointers may be NULL, dangling or unaligned; they can violate \ @@ -416,7 +416,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { let ty = Place::ty_from(&place.base, proj_base, &self.body.local_decls, self.tcx) .ty; - match ty.sty { + match ty.kind { ty::Adt(def, _) => match self.tcx.layout_scalar_valid_range(def.did) { (Bound::Unbounded, Bound::Unbounded) => {}, _ => { diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 614d5d2a4a2fb..857757ada53b7 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -372,7 +372,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let place = self.eval_place(&place, source_info)?; let mplace = place.try_as_mplace().ok()?; - if let ty::Slice(_) = mplace.layout.ty.sty { + if let ty::Slice(_) = mplace.layout.ty.kind { let len = mplace.meta.unwrap().to_usize(&self.ecx).unwrap(); Some(ImmTy::from_uint( @@ -380,7 +380,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?, ).into()) } else { - trace!("not slice: {:?}", mplace.layout.ty.sty); + trace!("not slice: {:?}", mplace.layout.ty.kind); None } }, @@ -552,7 +552,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { ScalarMaybeUndef::Scalar(one), ScalarMaybeUndef::Scalar(two) ) => { - let ty = &value.layout.ty.sty; + let ty = &value.layout.ty.kind; if let ty::Tuple(substs) = ty { *rval = Rvalue::Aggregate( Box::new(AggregateKind::Tuple), diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index caf588af851dd..2b66e602370cc 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -711,7 +711,7 @@ fn compute_layout<'tcx>( // Erase regions from the types passed in from typeck so we can compare them with // MIR types let allowed_upvars = tcx.erase_regions(upvars); - let allowed = match interior.sty { + let allowed = match interior.kind { ty::GeneratorWitness(s) => tcx.erase_late_bound_regions(&s), _ => bug!(), }; @@ -1124,7 +1124,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { let gen_ty = body.local_decls.raw[1].ty; // Get the interior types and substs which typeck computed - let (upvars, interior, discr_ty, movable) = match gen_ty.sty { + let (upvars, interior, discr_ty, movable) = match gen_ty.kind { ty::Generator(_, substs, movability) => { (substs.upvar_tys(def_id, tcx).collect(), substs.witness(def_id, tcx), diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 5ad026dc143c9..7f56c6f7986aa 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -177,7 +177,7 @@ impl Inliner<'tcx> { // Only consider direct calls to functions let terminator = bb_data.terminator(); if let TerminatorKind::Call { func: ref op, .. } = terminator.kind { - if let ty::FnDef(callee_def_id, substs) = op.ty(caller_body, self.tcx).sty { + if let ty::FnDef(callee_def_id, substs) = op.ty(caller_body, self.tcx).kind { let instance = Instance::resolve(self.tcx, param_env, callee_def_id, @@ -328,7 +328,7 @@ impl Inliner<'tcx> { } TerminatorKind::Call {func: Operand::Constant(ref f), .. } => { - if let ty::FnDef(def_id, _) = f.literal.ty.sty { + if let ty::FnDef(def_id, _) = f.literal.ty.kind { // Don't give intrinsics the extra penalty for calls let f = tcx.fn_sig(def_id); if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic { @@ -546,7 +546,7 @@ impl Inliner<'tcx> { assert!(args.next().is_none()); let tuple = Place::from(tuple); - let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_body, tcx).ty.sty { + let tuple_tys = if let ty::Tuple(s) = tuple.ty(caller_body, tcx).ty.kind { s } else { bug!("Closure arguments are not passed as a tuple"); diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index 0e04e63af4522..6b609e25ec042 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -102,7 +102,7 @@ impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> { if let Rvalue::Len(ref place) = *rvalue { let place_ty = place.ty(&self.body.local_decls, self.tcx).ty; - if let ty::Array(_, len) = place_ty.sty { + if let ty::Array(_, len) = place_ty.kind { let span = self.body.source_info(location).span; let constant = Constant { span, literal: len, user_ty: None }; self.optimizations.arrays_lengths.insert(location, constant); diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 795721f3b3f28..c1639b9b5bbf4 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -294,7 +294,7 @@ trait Qualif { if let box [proj_base @ .., elem] = &place.projection { if ProjectionElem::Deref == *elem { let base_ty = Place::ty_from(&place.base, proj_base, cx.body, cx.tcx).ty; - if let ty::Ref(..) = base_ty.sty { + if let ty::Ref(..) = base_ty.kind { return Self::in_place(cx, PlaceRef { base: &place.base, projection: proj_base, @@ -365,11 +365,11 @@ impl Qualif for HasMutInterior { // is allowed right now, and only in functions. if cx.mode == Mode::StaticMut { // Inside a `static mut`, &mut [...] is also allowed. - match ty.sty { + match ty.kind { ty::Array(..) | ty::Slice(_) => {} _ => return true, } - } else if let ty::Array(_, len) = ty.sty { + } else if let ty::Array(_, len) = ty.kind { // FIXME(eddyb) the `cx.mode == Mode::NonConstFn` condition // seems unnecessary, given that this is merely a ZST. match len.try_eval_usize(cx.tcx, cx.param_env) { @@ -500,7 +500,7 @@ impl Qualif for IsNotPromotable { } Rvalue::BinaryOp(op, ref lhs, _) if cx.mode == Mode::NonConstFn => { - if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(cx.body, cx.tcx).sty { + if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(cx.body, cx.tcx).kind { assert!(op == BinOp::Eq || op == BinOp::Ne || op == BinOp::Le || op == BinOp::Lt || op == BinOp::Ge || op == BinOp::Gt || @@ -526,7 +526,7 @@ impl Qualif for IsNotPromotable { _return_ty: Ty<'tcx>, ) -> bool { let fn_ty = callee.ty(cx.body, cx.tcx); - match fn_ty.sty { + match fn_ty.kind { ty::FnDef(def_id, _) => { match cx.tcx.fn_sig(def_id).abi() { Abi::RustIntrinsic | @@ -597,7 +597,7 @@ impl Qualif for IsNotImplicitlyPromotable { _return_ty: Ty<'tcx>, ) -> bool { if cx.mode == Mode::NonConstFn { - if let ty::FnDef(def_id, _) = callee.ty(cx.body, cx.tcx).sty { + if let ty::FnDef(def_id, _) = callee.ty(cx.body, cx.tcx).kind { // Never promote runtime `const fn` calls of // functions without `#[rustc_promotable]`. if !cx.tcx.is_promotable_const_fn(def_id) { @@ -1106,7 +1106,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { match self.mode { Mode::NonConstFn => {}, _ => { - if let ty::RawPtr(_) = base_ty.sty { + if let ty::RawPtr(_) = base_ty.kind { if !self.tcx.features().const_raw_ptr_deref { emit_feature_err( &self.tcx.sess.parse_sess, sym::const_raw_ptr_deref, @@ -1186,7 +1186,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { if let box [proj_base @ .., elem] = &place.projection { if *elem == ProjectionElem::Deref { let base_ty = Place::ty_from(&place.base, proj_base, self.body, self.tcx).ty; - if let ty::Ref(..) = base_ty.sty { + if let ty::Ref(..) = base_ty.kind { reborrow_place = Some(proj_base); } } @@ -1255,7 +1255,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { } Rvalue::BinaryOp(op, ref lhs, _) => { - if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).sty { + if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.body, self.tcx).kind { assert!(op == BinOp::Eq || op == BinOp::Ne || op == BinOp::Le || op == BinOp::Lt || op == BinOp::Ge || op == BinOp::Gt || @@ -1314,7 +1314,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { let fn_ty = func.ty(self.body, self.tcx); let mut callee_def_id = None; let mut is_shuffle = false; - match fn_ty.sty { + match fn_ty.kind { ty::FnDef(def_id, _) => { callee_def_id = Some(def_id); match self.tcx.fn_sig(def_id).abi() { diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index be83c823d4242..cf0ee1bf09222 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -32,7 +32,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) - if Some(pred.def_id()) == tcx.lang_items().sized_trait() { continue; } - match pred.skip_binder().self_ty().sty { + match pred.skip_binder().self_ty().kind { ty::Param(ref p) => { let generics = tcx.generics_of(current); let def = generics.type_param(p, tcx); @@ -79,7 +79,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) - fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, fn_def_id: DefId) -> McfResult { for ty in ty.walk() { - match ty.sty { + match ty.kind { ty::Ref(_, _, hir::Mutability::MutMutable) => return Err(( span, "mutable references in const fn are unstable".into(), @@ -342,7 +342,7 @@ fn check_terminator( cleanup: _, } => { let fn_ty = func.ty(body, tcx); - if let ty::FnDef(def_id, _) = fn_ty.sty { + if let ty::FnDef(def_id, _) = fn_ty.kind { // some intrinsics are waved through if called inside the // standard library. Users never need to call them directly diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 68fa082d29407..539645d0227f4 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -224,7 +224,7 @@ fn is_rustc_peek<'a, 'tcx>( if let Some(mir::Terminator { ref kind, source_info, .. }) = *terminator { if let mir::TerminatorKind::Call { func: ref oper, ref args, .. } = *kind { if let mir::Operand::Constant(ref func) = *oper { - if let ty::FnDef(def_id, _) = func.literal.ty.sty { + if let ty::FnDef(def_id, _) = func.literal.ty.kind { let abi = tcx.fn_sig(def_id).abi(); let name = tcx.item_name(def_id); if abi == Abi::RustIntrinsic && name == sym::rustc_peek { diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs index 34ad5cb5dc787..eb61cd2f657a2 100644 --- a/src/librustc_mir/transform/uniform_array_move_out.rs +++ b/src/librustc_mir/transform/uniform_array_move_out.rs @@ -69,7 +69,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> { } else { let place_ty = Place::ty_from(&src_place.base, proj_base, self.body, self.tcx).ty; - if let ty::Array(item_ty, const_size) = place_ty.sty { + if let ty::Array(item_ty, const_size) = place_ty.kind { if let Some(size) = const_size.try_eval_usize(self.tcx, self.param_env) { assert!(size <= u32::max_value() as u64, "uniform array move out doesn't supported @@ -224,7 +224,7 @@ impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut { let opt_size = opt_src_place.and_then(|src_place| { let src_ty = Place::ty_from(src_place.base, src_place.projection, body, tcx).ty; - if let ty::Array(_, ref size_o) = src_ty.sty { + if let ty::Array(_, ref size_o) = src_ty.kind { size_o.try_eval_usize(tcx, param_env) } else { None diff --git a/src/librustc_mir/util/alignment.rs b/src/librustc_mir/util/alignment.rs index a75c1af04f047..1bad85ec42d08 100644 --- a/src/librustc_mir/util/alignment.rs +++ b/src/librustc_mir/util/alignment.rs @@ -47,7 +47,7 @@ where ProjectionElem::Deref => break, ProjectionElem::Field(..) => { let ty = Place::ty_from(&place.base, proj_base, local_decls, tcx).ty; - match ty.sty { + match ty.kind { ty::Adt(def, _) if def.repr.packed() => { return true } diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index cf9ef55c17b34..96ba829358280 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -324,7 +324,7 @@ impl<'cx, 'tcx> crate::borrow_check::MirBorrowckCtxt<'cx, 'tcx> { ty: Ty<'_>, is_index: Option, ) -> DiagnosticBuilder<'cx> { - let type_name = match (&ty.sty, is_index) { + let type_name = match (&ty.kind, is_index) { (&ty::Array(_, _), Some(true)) | (&ty::Array(_, _), None) => "array", (&ty::Slice(_), _) => "slice", _ => span_bug!(move_from_span, "this path should not cause illegal move"), diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 52ad97bbde1d7..e1015edfa8eec 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -786,7 +786,7 @@ where /// ADT, both in the success case or if one of the destructors fail. fn open_drop(&mut self) -> BasicBlock { let ty = self.place_ty(self.place); - match ty.sty { + match ty.kind { ty::Closure(def_id, substs) => { let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect(); self.open_drop_for_tuple(&tys) diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index f2461f7016131..38b4fa354c15f 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -273,7 +273,7 @@ fn check_expr_kind<'a, 'tcx>( v: &mut CheckCrateVisitor<'a, 'tcx>, e: &'tcx hir::Expr, node_ty: Ty<'tcx>) -> Promotability { - let ty_result = match node_ty.sty { + let ty_result = match node_ty.kind { ty::Adt(def, _) if def.has_dtor(v.tcx) => { NotPromotable } @@ -298,7 +298,7 @@ fn check_expr_kind<'a, 'tcx>( if v.tables.is_method_call(e) { return NotPromotable; } - match v.tables.node_type(lhs.hir_id).sty { + match v.tables.node_type(lhs.hir_id).kind { ty::RawPtr(_) | ty::FnPtr(..) => { assert!(op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne || op.node == hir::BinOpKind::Le || op.node == hir::BinOpKind::Lt || @@ -427,7 +427,7 @@ fn check_expr_kind<'a, 'tcx>( if let Some(ref expr) = *option_expr { struct_result &= v.check_expr(&expr); } - if let ty::Adt(adt, ..) = v.tables.expr_ty(e).sty { + if let ty::Adt(adt, ..) = v.tables.expr_ty(e).kind { // unsafe_cell_type doesn't necessarily exist with no_core if Some(adt.did) == v.tcx.lang_items().unsafe_cell_type() { return NotPromotable; diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 1e61f78c357df..d7f5fdeb00c52 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -129,7 +129,7 @@ where fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { let tcx = self.def_id_visitor.tcx(); // InternalSubsts are not visited here because they are visited below in `super_visit_with`. - match ty.sty { + match ty.kind { ty::Adt(&ty::AdtDef { did: def_id, .. }, ..) | ty::Foreign(def_id) | ty::FnDef(def_id, ..) | @@ -144,7 +144,7 @@ where // Default type visitor doesn't visit signatures of fn types. // Something like `fn() -> Priv {my_func}` is considered a private type even if // `my_func` is public, so we need to visit signatures. - if let ty::FnDef(..) = ty.sty { + if let ty::FnDef(..) = ty.kind { if tcx.fn_sig(def_id).visit_with(self) { return true; } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 055ccf6c2c4f8..7b1a6a9765b80 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -515,7 +515,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { let expr_hir_id = self.tcx.hir().node_to_hir_id(expr.id); let hir_node = self.tcx.hir().expect_expr(expr_hir_id); let ty = self.tables.expr_ty_adjusted_opt(&hir_node); - if ty.is_none() || ty.unwrap().sty == ty::Error { + if ty.is_none() || ty.unwrap().kind == ty::Error { return None; } match expr.node { @@ -532,7 +532,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { return None; } }; - match self.tables.expr_ty_adjusted(&hir_node).sty { + match self.tables.expr_ty_adjusted(&hir_node).kind { ty::Adt(def, _) if !def.is_enum() => { let variant = &def.non_enum_variant(); let index = self.tcx.find_field_index(ident, variant).unwrap(); @@ -552,7 +552,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { } } ast::ExprKind::Struct(ref path, ..) => { - match self.tables.expr_ty_adjusted(&hir_node).sty { + match self.tables.expr_ty_adjusted(&hir_node).kind { ty::Adt(def, _) if !def.is_enum() => { let sub_span = path.segments.last().unwrap().ident.span; filter!(self.span_utils, sub_span); diff --git a/src/librustc_traits/chalk_context/mod.rs b/src/librustc_traits/chalk_context/mod.rs index 5c23ad4a4edfb..fe66b1932d5e8 100644 --- a/src/librustc_traits/chalk_context/mod.rs +++ b/src/librustc_traits/chalk_context/mod.rs @@ -278,7 +278,7 @@ impl context::ContextOps> for ChalkContext<'tcx> { } _ => false, }, - UnpackedKind::Type(ty) => match ty.sty { + UnpackedKind::Type(ty) => match ty.kind { ty::Bound(debruijn, bound_ty) => { debug_assert_eq!(debruijn, ty::INNERMOST); cvar == bound_ty.var diff --git a/src/librustc_traits/chalk_context/program_clauses/builtin.rs b/src/librustc_traits/chalk_context/program_clauses/builtin.rs index 71e18d2b6f949..cc5ca3d92c9c1 100644 --- a/src/librustc_traits/chalk_context/program_clauses/builtin.rs +++ b/src/librustc_traits/chalk_context/program_clauses/builtin.rs @@ -49,7 +49,7 @@ crate fn assemble_builtin_unsize_impls<'tcx>( target: Ty<'tcx>, clauses: &mut Vec>, ) { - match (&source.sty, &target.sty) { + match (&source.kind, &target.kind) { (ty::Dynamic(data_a, ..), ty::Dynamic(data_b, ..)) => { if data_a.principal_def_id() != data_b.principal_def_id() || data_b.auto_traits().any(|b| data_a.auto_traits().all(|a| a != b)) @@ -130,7 +130,7 @@ crate fn assemble_builtin_sized_impls<'tcx>( clauses.push(Clause::ForAll(ty::Binder::bind(clause))); }; - match &ty.sty { + match &ty.kind { // Non parametric primitive types. ty::Bool | ty::Char | @@ -234,7 +234,7 @@ crate fn assemble_builtin_copy_clone_impls<'tcx>( clauses.push(Clause::ForAll(ty::Binder::bind(clause))); }; - match &ty.sty { + match &ty.kind { // Implementations provided in libcore. ty::Bool | ty::Char | @@ -264,7 +264,7 @@ crate fn assemble_builtin_copy_clone_impls<'tcx>( } &ty::Closure(def_id, ..) => { let closure_ty = generic_types::closure(tcx, def_id); - let upvar_tys: Vec<_> = match &closure_ty.sty { + let upvar_tys: Vec<_> = match &closure_ty.kind { ty::Closure(_, substs) => { substs.upvar_tys(def_id, tcx).map(|ty| Kind::from(ty)).collect() }, diff --git a/src/librustc_traits/chalk_context/program_clauses/mod.rs b/src/librustc_traits/chalk_context/program_clauses/mod.rs index a49ca400f5a21..1b6a5902be69b 100644 --- a/src/librustc_traits/chalk_context/program_clauses/mod.rs +++ b/src/librustc_traits/chalk_context/program_clauses/mod.rs @@ -176,7 +176,7 @@ impl ChalkInferenceContext<'cx, 'tcx> { // associated type (rule `WellFormed-AssocTy`) // * custom rules for built-in types // * the type definition otherwise (rule `WellFormed-Type`) - let clauses = match ty.sty { + let clauses = match ty.kind { ty::Projection(data) => { self.infcx.tcx.program_clauses_for(data.item_def_id) } diff --git a/src/librustc_traits/chalk_context/resolvent_ops.rs b/src/librustc_traits/chalk_context/resolvent_ops.rs index c7aa6fe105e54..a871ad4b160e9 100644 --- a/src/librustc_traits/chalk_context/resolvent_ops.rs +++ b/src/librustc_traits/chalk_context/resolvent_ops.rs @@ -212,7 +212,7 @@ impl TypeRelation<'tcx> for AnswerSubstitutor<'cx, 'tcx> { let b = self.infcx.shallow_resolve(b); debug!("AnswerSubstitutor::tys(a = {:?}, b = {:?})", a, b); - if let &ty::Bound(debruijn, bound_ty) = &a.sty { + if let &ty::Bound(debruijn, bound_ty) = &a.kind { // Free bound var if debruijn == self.binder_index { self.unify_free_answer_var(bound_ty.var, b.into())?; @@ -220,7 +220,7 @@ impl TypeRelation<'tcx> for AnswerSubstitutor<'cx, 'tcx> { } } - match (&a.sty, &b.sty) { + match (&a.kind, &b.kind) { (&ty::Bound(a_debruijn, a_bound), &ty::Bound(b_debruijn, b_bound)) => { assert_eq!(a_debruijn, b_debruijn); assert_eq!(a_bound.var, b_bound.var); diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index ecd888b606981..a36b381bed343 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -105,7 +105,7 @@ fn dropck_outlives<'tcx>( debug!("dropck_outlives: ty from dtorck_types = {:?}", ty); - match ty.sty { + match ty.kind { // All parameters live for the duration of the // function. ty::Param(..) => {} @@ -166,7 +166,7 @@ fn dtorck_constraint_for_ty<'tcx>( }); } - let result = match ty.sty { + let result = match ty.kind { ty::Bool | ty::Char | ty::Int(_) diff --git a/src/librustc_traits/lowering/environment.rs b/src/librustc_traits/lowering/environment.rs index 9ff685bb4ee8a..759eced131981 100644 --- a/src/librustc_traits/lowering/environment.rs +++ b/src/librustc_traits/lowering/environment.rs @@ -25,7 +25,7 @@ impl ClauseVisitor<'a, 'tcx> { } fn visit_ty(&mut self, ty: Ty<'tcx>) { - match ty.sty { + match ty.kind { ty::Projection(data) => { self.round.extend( self.tcx.program_clauses_for(data.item_def_id) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 718d12484f741..2cd74281306f1 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1608,7 +1608,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Check if we have an enum variant. let mut variant_resolution = None; - if let ty::Adt(adt_def, _) = qself_ty.sty { + if let ty::Adt(adt_def, _) = qself_ty.kind { if adt_def.is_enum() { let variant_def = adt_def.variants.iter().find(|vd| { tcx.hygienic_eq(assoc_ident, vd.ident, adt_def.did) @@ -1626,7 +1626,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // Find the type of the associated item, and the trait where the associated // item is declared. - let bound = match (&qself_ty.sty, qself_res) { + let bound = match (&qself_ty.kind, qself_res) { (_, Res::SelfTy(Some(_), Some(impl_def_id))) => { // `Self` in an impl of a trait -- we have a concrete self type and a // trait reference. diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index ecdf28e5d7f0b..ab5cabcaa4f7f 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -189,7 +189,7 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { fcx.try_overloaded_deref(self.span, source, needs) .and_then(|InferOk { value: method, obligations: o }| { obligations.extend(o); - if let ty::Ref(region, _, mutbl) = method.sig.output().sty { + if let ty::Ref(region, _, mutbl) = method.sig.output().kind { Some(OverloadedDeref { region, mutbl, diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 710d847384e6c..e1f239d3d08dd 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -90,7 +90,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); // If the callee is a bare function or a closure, then we're all set. - match adjusted_ty.sty { + match adjusted_ty.kind { ty::FnDef(..) | ty::FnPtr(_) => { let adjustments = autoderef.adjust_steps(self, Needs::None); self.apply_adjustments(callee_expr, adjustments); @@ -212,7 +212,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let method = self.register_infer_ok_obligations(ok); let mut autoref = None; if borrow { - if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].sty { + if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind { let mutbl = match mutbl { hir::MutImmutable => AutoBorrowMutability::Immutable, hir::MutMutable => AutoBorrowMutability::Mutable { @@ -268,7 +268,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { arg_exprs: &'tcx [hir::Expr], expected: Expectation<'tcx>, ) -> Ty<'tcx> { - let (fn_sig, def_span) = match callee_ty.sty { + let (fn_sig, def_span) = match callee_ty.kind { ty::FnDef(def_id, _) => ( callee_ty.fn_sig(self.tcx), self.tcx.hir().span_if_local(def_id), diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index c216cc92b1e58..dfeb5fb958cd8 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -93,7 +93,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Ok(Some(PointerKind::Thin)); } - Ok(match t.sty { + Ok(match t.kind { ty::Slice(_) | ty::Str => Some(PointerKind::Length), ty::Dynamic(ref tty, ..) => Some(PointerKind::Vtable(tty.principal_def_id())), @@ -192,7 +192,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { // For better error messages, check for some obviously unsized // cases now. We do a more thorough check at the end, once // inference is more completely known. - match cast_ty.sty { + match cast_ty.kind { ty::Dynamic(..) | ty::Slice(..) => { check.report_cast_to_unsized_type(fcx); Err(ErrorReported) @@ -339,7 +339,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { "cast to unsized type: `{}` as `{}`", fcx.resolve_vars_if_possible(&self.expr_ty), tstr); - match self.expr_ty.sty { + match self.expr_ty.kind { ty::Ref(_, _, mt) => { let mtstr = match mt { hir::MutMutable => "mut ", @@ -455,7 +455,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { (Some(t_from), Some(t_cast)) => (t_from, t_cast), // Function item types may need to be reified before casts. (None, Some(t_cast)) => { - if let ty::FnDef(..) = self.expr_ty.sty { + if let ty::FnDef(..) = self.expr_ty.kind { // Attempt a coercion to a fn pointer type. let f = self.expr_ty.fn_sig(fcx.tcx); let res = fcx.try_coerce(self.expr, @@ -505,7 +505,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { (FnPtr, Int(_)) => Ok(CastKind::FnPtrAddrCast), (RPtr(p), Int(_)) | (RPtr(p), Float) => { - match p.ty.sty { + match p.ty.kind { ty::Int(_) | ty::Uint(_) | ty::Float(_) => { @@ -616,7 +616,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { // array-ptr-cast. if m_expr.mutbl == hir::MutImmutable && m_cast.mutbl == hir::MutImmutable { - if let ty::Array(ety, _) = m_expr.ty.sty { + if let ty::Array(ety, _) = m_expr.ty.kind { // Due to the limitations of LLVM global constants, // region pointers end up pointing at copies of // vector elements instead of the original values. diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index d626bff150020..bdf8f3b1d4ae6 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -186,7 +186,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected_ty ); - match expected_ty.sty { + match expected_ty.kind { ty::Dynamic(ref object_type, ..) => { let sig = object_type .projection_bounds() @@ -288,7 +288,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let arg_param_ty = self.resolve_vars_if_possible(&arg_param_ty); debug!("deduce_sig_from_projection: arg_param_ty={:?}", arg_param_ty); - match arg_param_ty.sty { + match arg_param_ty.kind { ty::Tuple(tys) => tys.into_iter().map(|k| k.expect_ty()).collect::>(), _ => return None, } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index dc536329251ca..e507fa31435ac 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -206,7 +206,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // // Note: does not attempt to resolve type variables we encounter. // See above for details. - match b.sty { + match b.kind { ty::RawPtr(mt_b) => { return self.coerce_unsafe_ptr(a, b, mt_b.mutbl); } @@ -219,7 +219,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { _ => {} } - match a.sty { + match a.kind { ty::FnDef(..) => { // Function items are coercible to any closure // type; function pointers are not (that would @@ -264,7 +264,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // to type check, we will construct the type that `&M*expr` would // yield. - let (r_a, mt_a) = match a.sty { + let (r_a, mt_a) = match a.kind { ty::Ref(r_a, ty, mutbl) => { let mt_a = ty::TypeAndMut { ty, mutbl }; coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?; @@ -426,7 +426,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // Now apply the autoref. We have to extract the region out of // the final ref type we got. - let r_borrow = match ty.sty { + let r_borrow = match ty.kind { ty::Ref(r_borrow, _, _) => r_borrow, _ => span_bug!(span, "expected a ref type, got {:?}", ty), }; @@ -470,7 +470,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // that, at which point we will need extra checks on the target here. // Handle reborrows before selecting `Source: CoerceUnsized`. - let reborrow = match (&source.sty, &target.sty) { + let reborrow = match (&source.kind, &target.kind) { (&ty::Ref(_, ty_a, mutbl_a), &ty::Ref(_, _, mutbl_b)) => { coerce_mutbls(mutbl_a, mutbl_b)?; @@ -568,7 +568,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let trait_ref = match obligation.predicate { ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => { if unsize_did == tr.def_id() { - let sty = &tr.skip_binder().input_types().nth(1).unwrap().sty; + let sty = &tr.skip_binder().input_types().nth(1).unwrap().kind; if let ty::Tuple(..) = sty { debug!("coerce_unsized: found unsized tuple coercion"); has_unsized_tuple_coercion = true; @@ -589,7 +589,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let self_ty = trait_ref.skip_binder().self_ty(); let unsize_ty = trait_ref.skip_binder().input_types().nth(1).unwrap(); debug!("coerce_unsized: ambiguous unsize case for {:?}", trait_ref); - match (&self_ty.sty, &unsize_ty.sty) { + match (&self_ty.kind, &unsize_ty.kind) { (ty::Infer(ty::TyVar(v)), ty::Dynamic(..)) if self.type_var_is_sized(*v) => { debug!("coerce_unsized: have sized infer {:?}", v); @@ -650,7 +650,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { where F: FnOnce(Ty<'tcx>) -> Vec>, G: FnOnce(Ty<'tcx>) -> Vec> { - if let ty::FnPtr(fn_ty_b) = b.sty { + if let ty::FnPtr(fn_ty_b) = b.kind { if let (hir::Unsafety::Normal, hir::Unsafety::Unsafe) = (fn_ty_a.unsafety(), fn_ty_b.unsafety()) { @@ -687,7 +687,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let b = self.shallow_resolve(b); debug!("coerce_from_fn_item(a={:?}, b={:?})", a, b); - match b.sty { + match b.kind { ty::FnPtr(_) => { let a_sig = a.fn_sig(self.tcx); // Intrinsics are not coercible to function pointers @@ -737,7 +737,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let b = self.shallow_resolve(b); - match b.sty { + match b.kind { ty::FnPtr(fn_ty) if self.tcx.upvars(def_id_a).map_or(true, |v| v.is_empty()) => { // We coerce the closure, which has fn type // `extern "rust-call" fn((arg0,arg1,...)) -> _` @@ -765,7 +765,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { -> CoerceResult<'tcx> { debug!("coerce_unsafe_ptr(a={:?}, b={:?})", a, b); - let (is_ref, mt_a) = match a.sty { + let (is_ref, mt_a) = match a.kind { ty::Ref(_, ty, mutbl) => (true, ty::TypeAndMut { ty, mutbl }), ty::RawPtr(mt) => (false, mt), _ => return self.unify_and(a, b, identity) @@ -860,7 +860,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Special-case that coercion alone cannot handle: // Two function item types of differing IDs or InternalSubsts. - if let (&ty::FnDef(..), &ty::FnDef(..)) = (&prev_ty.sty, &new_ty.sty) { + if let (&ty::FnDef(..), &ty::FnDef(..)) = (&prev_ty.kind, &new_ty.kind) { // Don't reify if the function types have a LUB, i.e., they // are the same function and their parameters have a LUB. let lub_ty = self.commit_if_ok(|_| { @@ -929,7 +929,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Adjustment { kind: Adjust::Deref(_), .. }, Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(_, mutbl_adj)), .. } ] => { - match self.node_ty(expr.hir_id).sty { + match self.node_ty(expr.hir_id).kind { ty::Ref(_, _, mt_orig) => { let mutbl_adj: hir::Mutability = mutbl_adj.into(); // Reborrow that we can safely ignore, because diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 63137bad52ff8..6c94f833196fb 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -150,7 +150,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, expr_ty: Ty<'tcx>, ) { - if let ty::Adt(expected_adt, substs) = expected.sty { + if let ty::Adt(expected_adt, substs) = expected.kind { if !expected_adt.is_enum() { return; } @@ -351,8 +351,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // and make a good suggestion, so don't bother. let is_macro = sp.from_expansion(); - match (&expr.node, &expected.sty, &checked_ty.sty) { - (_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.sty, &check.sty) { + match (&expr.node, &expected.kind, &checked_ty.kind) { + (_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.kind, &check.kind) { (&ty::Str, &ty::Array(arr, _)) | (&ty::Str, &ty::Slice(arr)) if arr == self.tcx.types.u8 => { if let hir::ExprKind::Lit(_) = expr.node { @@ -650,8 +650,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "{}{}{}{}", if needs_paren { "(" } else { "" }, if let (ty::Int(_), ty::Float(_)) | (ty::Uint(_), ty::Float(_)) = ( - &expected_ty.sty, - &checked_ty.sty, + &expected_ty.kind, + &checked_ty.kind, ) { // Remove fractional part from literal, for example `42.0f32` into `42` let src = src.trim_end_matches(&checked_ty.to_string()); @@ -695,7 +695,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); }; - match (&expected_ty.sty, &checked_ty.sty) { + match (&expected_ty.kind, &checked_ty.kind) { (&ty::Int(ref exp), &ty::Int(ref found)) => { let is_fallible = match (found.bit_width(), exp.bit_width()) { (Some(found), Some(exp)) if found > exp => true, diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index babffe479bc2e..a144e5938c3a8 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -32,7 +32,7 @@ use syntax_pos::Span; pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), ErrorReported> { let dtor_self_type = tcx.type_of(drop_impl_did); let dtor_predicates = tcx.predicates_of(drop_impl_did); - match dtor_self_type.sty { + match dtor_self_type.kind { ty::Adt(adt_def, self_to_impl_substs) => { ensure_drop_params_and_item_params_correspond( tcx, diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 6b694bfc8da25..97fcfd7151a1c 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -305,7 +305,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_expr_box(&self, expr: &'tcx hir::Expr, expected: Expectation<'tcx>) -> Ty<'tcx> { let expected_inner = expected.to_option(self).map_or(NoExpectation, |ty| { - match ty.sty { + match ty.kind { ty::Adt(def, _) if def.is_box() => Expectation::rvalue_hint(self, ty.boxed_ty()), _ => NoExpectation @@ -343,7 +343,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if let Some(ok) = self.try_overloaded_deref( expr.span, oprnd_t, needs) { let method = self.register_infer_ok_obligations(ok); - if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].sty { + if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind { let mutbl = match mutbl { hir::MutImmutable => AutoBorrowMutability::Immutable, hir::MutMutable => AutoBorrowMutability::Mutable { @@ -386,7 +386,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::UnNot => { let result = self.check_user_unop(expr, oprnd_t, unop); // If it's builtin, we can reuse the type, this helps inference. - if !(oprnd_t.is_integral() || oprnd_t.sty == ty::Bool) { + if !(oprnd_t.is_integral() || oprnd_t.kind == ty::Bool) { oprnd_t = result; } } @@ -410,7 +410,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr, ) -> Ty<'tcx> { let hint = expected.only_has_type(self).map_or(NoExpectation, |ty| { - match ty.sty { + match ty.kind { ty::Ref(_, ty, _) | ty::RawPtr(ty::TypeAndMut { ty, .. }) => { if oprnd.is_place_expr() { // Places may legitimately have unsized types. @@ -464,7 +464,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0, }; - if let ty::FnDef(..) = ty.sty { + if let ty::FnDef(..) = ty.kind { let fn_sig = ty.fn_sig(tcx); if !tcx.features().unsized_locals { // We want to remove some Sized bounds from std functions, @@ -556,7 +556,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { assert!(e_ty.is_unit()); let ty = coerce.expected_ty(); coerce.coerce_forced_unit(self, &cause, &mut |err| { - let val = match ty.sty { + let val = match ty.kind { ty::Bool => "true", ty::Char => "'a'", ty::Int(_) | ty::Uint(_) => "42", @@ -838,7 +838,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error, Some(args), ) { - if let ty::Adt(..) = rcvr_t.sty { + if let ty::Adt(..) = rcvr_t.kind { // Try alternative arbitrary self types that could fulfill this call. // FIXME: probe for all types that *could* be arbitrary self-types, not // just this whitelist. @@ -889,7 +889,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &'tcx hir::Expr ) -> Ty<'tcx> { let uty = expected.to_option(self).and_then(|uty| { - match uty.sty { + match uty.kind { ty::Array(ty, _) | ty::Slice(ty) => Some(ty), _ => None } @@ -949,7 +949,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let uty = match expected { ExpectHasType(uty) => { - match uty.sty { + match uty.kind { ty::Array(ty, _) | ty::Slice(ty) => Some(ty), _ => None } @@ -989,7 +989,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let flds = expected.only_has_type(self).and_then(|ty| { let ty = self.resolve_type_vars_with_obligations(ty); - match ty.sty { + match ty.kind { ty::Tuple(ref flds) => Some(&flds[..]), _ => None } @@ -1055,7 +1055,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // when certain fields are assumed to exist that in fact do not. if !error_happened { self.check_expr_has_type_or_error(base_expr, adt_ty); - match adt_ty.sty { + match adt_ty.kind { ty::Adt(adt, substs) if adt.is_struct() => { let fru_field_types = adt.non_enum_variant().fields.iter().map(|f| { self.normalize_associated_types_in(expr.span, &f.ty(self.tcx, substs)) @@ -1095,7 +1095,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // re-link the regions that EIfEO can erase. self.demand_eqtype(span, adt_ty_hint, adt_ty); - let (substs, adt_kind, kind_name) = match &adt_ty.sty { + let (substs, adt_kind, kind_name) = match &adt_ty.kind { &ty::Adt(adt, substs) => { (substs, adt.adt_kind(), adt.variant_descr()) } @@ -1217,7 +1217,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let mut err = self.type_error_struct_with_diag( field.ident.span, - |actual| match ty.sty { + |actual| match ty.kind { ty::Adt(adt, ..) if adt.is_enum() => { struct_span_err!(self.tcx.sess, field.ident.span, E0559, "{} `{}::{}` has no field named `{}`", @@ -1256,7 +1256,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MaybeIncorrect, ); } else { - match ty.sty { + match ty.kind { ty::Adt(adt, ..) => { if adt.is_enum() { err.span_label(field.ident.span, format!( @@ -1338,7 +1338,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut private_candidate = None; let mut autoderef = self.autoderef(expr.span, expr_t); while let Some((base_t, _)) = autoderef.next() { - match base_t.sty { + match base_t.kind { ty::Adt(base_def, substs) if !base_def.is_enum() => { debug!("struct named {:?}", base_t); let (ident, def_scope) = @@ -1392,7 +1392,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if !expr_t.is_primitive_ty() { let mut err = self.no_such_field_err(field.span, field, expr_t); - match expr_t.sty { + match expr_t.kind { ty::Adt(def, _) if !def.is_enum() => { self.suggest_fields_on_recordish(&mut err, def, field); } @@ -1600,7 +1600,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "cannot index into a value of type `{}`", base_t); // Try to give some advice about indexing tuples. - if let ty::Tuple(..) = base_t.sty { + if let ty::Tuple(..) = base_t.kind { let mut needs_note = true; // If the index is an integer, we can show the actual // fixed expression: diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 5df0010b63eb2..5d4893ae75483 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -277,7 +277,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { .autoderef(self.span, self_ty) .include_raw_pointers() .filter_map(|(ty, _)| - match ty.sty { + match ty.kind { ty::Dynamic(ref data, ..) => { Some(closure(self, ty, data.principal().unwrap_or_else(|| { span_bug!(self.span, "calling trait method on empty object?") @@ -467,7 +467,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { if let Adjust::Deref(Some(ref mut deref)) = adjustment.kind { if let Some(ok) = self.try_overloaded_deref(expr.span, source, needs) { let method = self.register_infer_ok_obligations(ok); - if let ty::Ref(region, _, mutbl) = method.sig.output().sty { + if let ty::Ref(region, _, mutbl) = method.sig.output().kind { *deref = OverloadedDeref { region, mutbl, @@ -526,7 +526,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { debug!("convert_place_op_to_mutable: method={:?}", method); self.write_method_call(expr.hir_id, method); - let (region, mutbl) = if let ty::Ref(r, _, mutbl) = method.sig.inputs()[0].sty { + let (region, mutbl) = if let ty::Ref(r, _, mutbl) = method.sig.inputs()[0].kind { (r, mutbl) } else { span_bug!(expr.span, "input to place op is not a ref?"); @@ -592,7 +592,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { } }) .any(|trait_pred| { - match trait_pred.skip_binder().self_ty().sty { + match trait_pred.skip_binder().self_ty().kind { ty::Dynamic(..) => true, _ => false, } diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 1509c0f8a2196..2be311127214d 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -410,7 +410,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.tcx; // Check if we have an enum variant. - if let ty::Adt(adt_def, _) = self_ty.sty { + if let ty::Adt(adt_def, _) = self_ty.kind { if adt_def.is_enum() { let variant_def = adt_def.variants.iter().find(|vd| { tcx.hygienic_eq(method_name, vd.ident, adt_def.did) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index c8838311e8dbf..593cf77a4a6c7 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -419,7 +419,7 @@ fn method_autoderef_steps<'tcx>( from_unsafe_deref: reached_raw_pointer, unsize: false, }; - if let ty::RawPtr(_) = ty.sty { + if let ty::RawPtr(_) = ty.kind { // all the subsequent steps will be from_unsafe_deref reached_raw_pointer = true; } @@ -428,7 +428,7 @@ fn method_autoderef_steps<'tcx>( .collect(); let final_ty = autoderef.maybe_ambiguous_final_ty(); - let opt_bad_ty = match final_ty.sty { + let opt_bad_ty = match final_ty.kind { ty::Infer(ty::TyVar(_)) | ty::Error => { Some(MethodAutoderefBadTy { @@ -541,7 +541,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { debug!("assemble_probe: self_ty={:?}", self_ty); let lang_items = self.tcx.lang_items(); - match self_ty.value.value.sty { + match self_ty.value.value.kind { ty::Dynamic(ref data, ..) => { if let Some(p) = data.principal() { // Subtle: we can't use `instantiate_query_response` here: using it will @@ -735,7 +735,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { debug!("assemble_inherent_candidates_from_object(self_ty={:?})", self_ty); - let principal = match self_ty.sty { + let principal = match self_ty.kind { ty::Dynamic(ref data, ..) => Some(data), _ => None }.and_then(|data| data.principal()).unwrap_or_else(|| { @@ -773,7 +773,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { .filter_map(|predicate| { match *predicate { ty::Predicate::Trait(ref trait_predicate) => { - match trait_predicate.skip_binder().trait_ref.self_ty().sty { + match trait_predicate.skip_binder().trait_ref.self_ty().kind { ty::Param(ref p) if *p == param_ty => { Some(trait_predicate.to_poly_trait_ref()) } @@ -1073,7 +1073,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { pick.autoderefs = step.autoderefs; // Insert a `&*` or `&mut *` if this is a reference type: - if let ty::Ref(_, _, mutbl) = step.self_ty.value.value.sty { + if let ty::Ref(_, _, mutbl) = step.self_ty.value.value.kind { pick.autoderefs += 1; pick.autoref = Some(mutbl); } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 4c681544978e5..408532d1d1ee8 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -26,7 +26,7 @@ use super::probe::Mode; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool { let tcx = self.tcx; - match ty.sty { + match ty.kind { // Not all of these (e.g., unsafe fns) implement `FnOnce`, // so we look for these beforehand. ty::Closure(..) | @@ -339,7 +339,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } } - if let ty::RawPtr(_) = &actual.sty { + if let ty::RawPtr(_) = &actual.kind { err.note("try using `<*const T>::as_ref()` to get a reference to the \ type behind the pointer: https://doc.rust-lang.org/std/\ primitive.pointer.html#method.as_ref"); @@ -372,7 +372,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let SelfSource::MethodCall(expr) = source { let field_receiver = self .autoderef(span, rcvr_ty) - .find_map(|(ty, _)| match ty.sty { + .find_map(|(ty, _)| match ty.kind { ty::Adt(def, substs) if !def.is_enum() => { let variant = &def.non_enum_variant(); self.tcx.find_field_index(item_name, variant).map(|index| { @@ -701,9 +701,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { candidates.sort_by(|a, b| a.cmp(b).reverse()); candidates.dedup(); - let param_type = match rcvr_ty.sty { + let param_type = match rcvr_ty.kind { ty::Param(param) => Some(param), - ty::Ref(_, ty, _) => match ty.sty { + ty::Ref(_, ty, _) => match ty.kind { ty::Param(param) => Some(param), _ => None, } @@ -815,7 +815,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr_ty: Ty<'tcx>, source: SelfSource<'_>) -> bool { fn is_local(ty: Ty<'_>) -> bool { - match ty.sty { + match ty.kind { ty::Adt(def, _) => def.did.is_local(), ty::Foreign(did) => did.is_local(), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 02f4f2a3744c6..1d572c141211b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -316,7 +316,7 @@ impl<'a, 'tcx> Expectation<'tcx> { /// See the test case `test/ui/coerce-expect-unsized.rs` and #20169 /// for examples of where this comes up,. fn rvalue_hint(fcx: &FnCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> { - match fcx.tcx.struct_tail_without_normalization(ty).sty { + match fcx.tcx.struct_tail_without_normalization(ty).kind { ty::Slice(_) | ty::Str | ty::Dynamic(..) => { ExpectRvalueLikeUnsized(ty) } @@ -1230,7 +1230,7 @@ fn check_fn<'a, 'tcx>( // only happens if compilation succeeded fcx.tcx.sess.has_panic_handler.try_set_same(true); - if declared_ret_ty.sty != ty::Never { + if declared_ret_ty.kind != ty::Never { fcx.tcx.sess.span_err( decl.output.span(), "return type should be `!`", @@ -1240,8 +1240,8 @@ fn check_fn<'a, 'tcx>( let inputs = fn_sig.inputs(); let span = fcx.tcx.hir().span(fn_id); if inputs.len() == 1 { - let arg_is_panic_info = match inputs[0].sty { - ty::Ref(region, ty, mutbl) => match ty.sty { + let arg_is_panic_info = match inputs[0].kind { + ty::Ref(region, ty, mutbl) => match ty.kind { ty::Adt(ref adt, _) => { adt.did == panic_info_did && mutbl == hir::Mutability::MutImmutable && @@ -1283,7 +1283,7 @@ fn check_fn<'a, 'tcx>( if let Some(alloc_error_handler_did) = fcx.tcx.lang_items().oom() { if alloc_error_handler_did == fcx.tcx.hir().local_def_id(fn_id) { if let Some(alloc_layout_did) = fcx.tcx.lang_items().alloc_layout() { - if declared_ret_ty.sty != ty::Never { + if declared_ret_ty.kind != ty::Never { fcx.tcx.sess.span_err( decl.output.span(), "return type should be `!`", @@ -1293,7 +1293,7 @@ fn check_fn<'a, 'tcx>( let inputs = fn_sig.inputs(); let span = fcx.tcx.hir().span(fn_id); if inputs.len() == 1 { - let arg_is_alloc_layout = match inputs[0].sty { + let arg_is_alloc_layout = match inputs[0].kind { ty::Adt(ref adt, _) => { adt.did == alloc_layout_did }, @@ -1458,7 +1458,7 @@ fn check_opaque_for_cycles<'tcx>( "opaque type expands to a recursive type", ); err.span_label(span, "expands to a recursive type"); - if let ty::Opaque(..) = partially_expanded_type.sty { + if let ty::Opaque(..) = partially_expanded_type.kind { err.note("type resolves to itself"); } else { err.note(&format!("expanded type is `{}`", partially_expanded_type)); @@ -1884,7 +1884,7 @@ fn check_representable(tcx: TyCtxt<'_>, sp: Span, item_def_id: DefId) -> bool { pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) { let t = tcx.type_of(def_id); - if let ty::Adt(def, substs) = t.sty { + if let ty::Adt(def, substs) = t.kind { if def.is_struct() { let fields = &def.non_enum_variant().fields; if fields.is_empty() { @@ -1898,7 +1898,7 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: DefId) { .emit(); return; } - match e.sty { + match e.kind { ty::Param(_) => { /* struct(T, T, T, T) is ok */ } _ if e.is_machine() => { /* struct(u8, u8, u8, u8) is ok */ } _ => { @@ -1945,7 +1945,7 @@ fn check_packed_inner(tcx: TyCtxt<'_>, def_id: DefId, stack: &mut Vec) -> debug!("check_packed_inner: {:?} is recursive", t); return false; } - if let ty::Adt(def, substs) = t.sty { + if let ty::Adt(def, substs) = t.kind { if def.is_struct() || def.is_union() { if tcx.adt_def(def.did).repr.align.is_some() { return true; @@ -1954,7 +1954,7 @@ fn check_packed_inner(tcx: TyCtxt<'_>, def_id: DefId, stack: &mut Vec) -> stack.push(def_id); for field in &def.non_enum_variant().fields { let f = field.ty(tcx, substs); - if let ty::Adt(def, _) = f.sty { + if let ty::Adt(def, _) = f.kind { if check_packed_inner(tcx, def.did, stack) { return true; } @@ -2974,7 +2974,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut self_ty = adjusted_ty; if unsize { // We only unsize arrays here. - if let ty::Array(element_ty, _) = adjusted_ty.sty { + if let ty::Array(element_ty, _) = adjusted_ty.kind { self_ty = self.tcx.mk_slice(element_ty); } else { continue; @@ -2996,7 +2996,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let method = self.register_infer_ok_obligations(ok); let mut adjustments = autoderef.adjust_steps(self, needs); - if let ty::Ref(region, _, r_mutbl) = method.sig.inputs()[0].sty { + if let ty::Ref(region, _, r_mutbl) = method.sig.inputs()[0].kind { let mutbl = match r_mutbl { hir::MutImmutable => AutoBorrowMutability::Immutable, hir::MutMutable => AutoBorrowMutability::Mutable { @@ -3147,7 +3147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "self_type_matches_expected_vid(trait_ref={:?}, self_ty={:?}, expected_vid={:?})", trait_ref, self_ty, expected_vid ); - match self_ty.sty { + match self_ty.kind { ty::Infer(ty::TyVar(found_vid)) => { // FIXME: consider using `sub_root_var` here so we // can see through subtyping. @@ -3272,7 +3272,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let formal_tys = if tuple_arguments == TupleArguments { let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]); - match tuple_type.sty { + match tuple_type.kind { ty::Tuple(arg_types) if arg_types.len() != args.len() => { param_count_error(arg_types.len(), args.len(), "E0057", false, false); expected_arg_tys = vec![]; @@ -3280,7 +3280,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ty::Tuple(arg_types) => { expected_arg_tys = match expected_arg_tys.get(0) { - Some(&ty) => match ty.sty { + Some(&ty) => match ty.kind { ty::Tuple(ref tys) => tys.iter().map(|k| k.expect_ty()).collect(), _ => vec![], }, @@ -3421,7 +3421,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // There are a few types which get autopromoted when passed via varargs // in C but we just error out instead and require explicit casts. let arg_ty = self.structurally_resolved_type(arg.span, arg_ty); - match arg_ty.sty { + match arg_ty.kind { ty::Float(ast::FloatTy::F32) => { variadic_error(tcx.sess, arg.span, arg_ty, "c_double"); } @@ -3548,7 +3548,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => tcx.mk_mach_uint(t), ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => { let opt_ty = expected.to_option(self).and_then(|ty| { - match ty.sty { + match ty.kind { ty::Int(_) | ty::Uint(_) => Some(ty), ty::Char => Some(tcx.types.u8), ty::RawPtr(..) => Some(tcx.types.usize), @@ -3561,7 +3561,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ast::LitKind::Float(_, t) => tcx.mk_mach_float(t), ast::LitKind::FloatUnsuffixed(_) => { let opt_ty = expected.to_option(self).and_then(|ty| { - match ty.sty { + match ty.kind { ty::Float(_) => Some(ty), _ => None } @@ -3657,7 +3657,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; } Res::Def(DefKind::Variant, _) => { - match ty.sty { + match ty.kind { ty::Adt(adt, substs) => { Some((adt.variant_of_res(def), adt.did, substs)) } @@ -3669,7 +3669,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | Res::Def(DefKind::TyAlias, _) | Res::Def(DefKind::AssocTy, _) | Res::SelfTy(..) => { - match ty.sty { + match ty.kind { ty::Adt(adt, substs) if !adt.is_enum() => { Some((adt.non_enum_variant(), adt.did, substs)) } @@ -4163,13 +4163,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { found: Ty<'tcx>, ) -> bool { let hir = self.tcx.hir(); - let (def_id, sig) = match found.sty { + let (def_id, sig) = match found.kind { ty::FnDef(def_id, _) => (def_id, found.fn_sig(self.tcx)), ty::Closure(def_id, substs) => { // We don't use `closure_sig` to account for malformed closures like // `|_: [_; continue]| {}` and instead we don't suggest anything. let closure_sig_ty = substs.closure_sig_ty(def_id, self.tcx); - (def_id, match closure_sig_ty.sty { + (def_id, match closure_sig_ty.kind { ty::FnPtr(sig) => sig, _ => return false, }) @@ -4283,7 +4283,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } else if let (ty::FnDef(def_id, ..), true) = ( - &found.sty, + &found.kind, self.suggest_fn_call(err, expr, expected, found), ) { if let Some(sp) = self.tcx.hir().span_if_local(*def_id) { @@ -4453,7 +4453,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = AstConv::ast_ty_to_ty(self, ty); debug!("suggest_missing_return_type: return type {:?}", ty); debug!("suggest_missing_return_type: expected type {:?}", ty); - if ty.sty == expected.sty { + if ty.kind == expected.kind { err.span_label(sp, format!("expected `{}` because of return type", expected)); return true; @@ -4699,7 +4699,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = self.impl_self_ty(span, impl_def_id).ty; let adt_def = ty.ty_adt_def(); - match ty.sty { + match ty.kind { ty::Adt(adt_def, substs) if adt_def.has_ctor() => { let variant = adt_def.non_enum_variant(); let ctor_def_id = variant.ctor_def_id.unwrap(); @@ -4999,10 +4999,10 @@ pub fn check_bounds_are_used<'tcx>(tcx: TyCtxt<'tcx>, generics: &ty::Generics, t let mut types_used = vec![false; own_counts.types]; for leaf_ty in ty.walk() { - if let ty::Param(ty::ParamTy { index, .. }) = leaf_ty.sty { + if let ty::Param(ty::ParamTy { index, .. }) = leaf_ty.kind { debug!("found use of ty param num {}", index); types_used[index as usize - own_counts.lifetimes] = true; - } else if let ty::Error = leaf_ty.sty { + } else if let ty::Error = leaf_ty.kind { // If there is already another error, do not emit // an error for not using a type parameter. assert!(tcx.sess.has_errors()); diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 956d04ff6229b..f9df2d1d848ff 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -202,7 +202,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(method) => { let by_ref_binop = !op.node.is_by_value(); if is_assign == IsAssign::Yes || by_ref_binop { - if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].sty { + if let ty::Ref(region, _, mutbl) = method.sig.inputs()[0].kind { let mutbl = match mutbl { hir::MutImmutable => AutoBorrowMutability::Immutable, hir::MutMutable => AutoBorrowMutability::Mutable { @@ -219,7 +219,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } if by_ref_binop { - if let ty::Ref(region, _, mutbl) = method.sig.inputs()[1].sty { + if let ty::Ref(region, _, mutbl) = method.sig.inputs()[1].kind { let mutbl = match mutbl { hir::MutImmutable => AutoBorrowMutability::Immutable, hir::MutMutable => AutoBorrowMutability::Mutable { @@ -268,7 +268,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { op.node.as_str(), lhs_ty), ); let mut suggested_deref = false; - if let Ref(_, rty, _) = lhs_ty.sty { + if let Ref(_, rty, _) = lhs_ty.kind { if { self.infcx.type_is_copy_modulo_regions(self.param_env, rty, @@ -315,7 +315,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // This has nothing here because it means we did string // concatenation (e.g., "Hello " += "World!"). This means // we don't want the note in the else clause to be emitted - } else if let ty::Param(_) = lhs_ty.sty { + } else if let ty::Param(_) = lhs_ty.kind { // FIXME: point to span of param err.note(&format!( "`{}` might need a bound for `{}`", @@ -358,7 +358,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let mut suggested_deref = false; - if let Ref(_, rty, _) = lhs_ty.sty { + if let Ref(_, rty, _) = lhs_ty.kind { if { self.infcx.type_is_copy_modulo_regions(self.param_env, rty, @@ -406,7 +406,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // This has nothing here because it means we did string // concatenation (e.g., "Hello " + "World!"). This means // we don't want the note in the else clause to be emitted - } else if let ty::Param(_) = lhs_ty.sty { + } else if let ty::Param(_) = lhs_ty.kind { // FIXME: point to span of param err.note(&format!( "`{}` might need a bound for `{}`", @@ -443,7 +443,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { is_assign: IsAssign, ) -> bool /* did we suggest to call a function because of missing parenthesis? */ { err.span_label(span, ty.to_string()); - if let FnDef(def_id, _) = ty.sty { + if let FnDef(def_id, _) = ty.kind { let source_map = self.tcx.sess.source_map(); let hir_id = match self.tcx.hir().as_local_hir_id(def_id) { Some(hir_id) => hir_id, @@ -461,7 +461,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; - let other_ty = if let FnDef(def_id, _) = other_ty.sty { + let other_ty = if let FnDef(def_id, _) = other_ty.kind { let hir_id = match self.tcx.hir().as_local_hir_id(def_id) { Some(hir_id) => hir_id, None => return false, @@ -531,10 +531,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let is_std_string = |ty| &format!("{:?}", ty) == "std::string::String"; - match (&lhs_ty.sty, &rhs_ty.sty) { + match (&lhs_ty.kind, &rhs_ty.kind) { (&Ref(_, l_ty, _), &Ref(_, r_ty, _)) // &str or &String + &str, &String or &&str - if (l_ty.sty == Str || is_std_string(l_ty)) && ( - r_ty.sty == Str || is_std_string(r_ty) || + if (l_ty.kind == Str || is_std_string(l_ty)) && ( + r_ty.kind == Str || is_std_string(r_ty) || &format!("{:?}", rhs_ty) == "&&str" ) => { @@ -568,7 +568,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { true } (&Ref(_, l_ty, _), &Adt(..)) // Handle `&str` & `&String` + `String` - if (l_ty.sty == Str || is_std_string(l_ty)) && is_std_string(rhs_ty) => + if (l_ty.kind == Str || is_std_string(l_ty)) && is_std_string(rhs_ty) => { err.span_label( op.span, @@ -626,12 +626,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { op.as_str(), actual); err.span_label(ex.span, format!("cannot apply unary \ operator `{}`", op.as_str())); - match actual.sty { + match actual.kind { Uint(_) if op == hir::UnNeg => { err.note("unsigned values cannot be negated"); }, Str | Never | Char | Tuple(_) | Array(_,_) => {}, - Ref(_, ref lty, _) if lty.sty == Str => {}, + Ref(_, ref lty, _) if lty.kind == Str => {}, _ => { let missing_trait = match op { hir::UnNeg => "std::ops::Neg", diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 2cd8507d753a6..b9311f6b512c5 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -215,7 +215,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { PatKind::Slice(..) => true, PatKind::Lit(ref lt) => { let ty = self.check_expr(lt); - match ty.sty { + match ty.kind { ty::Ref(..) => false, _ => true, } @@ -252,7 +252,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // See the examples in `ui/match-defbm*.rs`. let mut pat_adjustments = vec![]; - while let ty::Ref(_, inner_ty, inner_mutability) = expected.sty { + while let ty::Ref(_, inner_ty, inner_mutability) = expected.kind { debug!("inspecting {:?}", expected); debug!("current discriminant is Ref, inserting implicit deref"); @@ -299,8 +299,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let hir::ExprKind::Lit(ref lt) = lt.node { if let ast::LitKind::ByteStr(_) = lt.node { let expected_ty = self.structurally_resolved_type(span, expected); - if let ty::Ref(_, r_ty, _) = expected_ty.sty { - if let ty::Slice(_) = r_ty.sty { + if let ty::Ref(_, r_ty, _) = expected_ty.kind { + if let ty::Slice(_) = r_ty.kind { let tcx = self.tcx; pat_ty = tcx.mk_imm_ref( tcx.lifetimes.re_static, @@ -498,7 +498,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &Pat) -> bool { if let PatKind::Binding(..) = inner.node { if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true) { - if let ty::Dynamic(..) = mt.ty.sty { + if let ty::Dynamic(..) = mt.ty.kind { // This is "x = SomeTrait" being reduced from // "let &x = &SomeTrait" or "let box x = Box", an error. let type_str = self.ty_to_string(expected); @@ -664,7 +664,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if subpats.len() == variant.fields.len() || subpats.len() < variant.fields.len() && ddpos.is_some() { - let substs = match pat_ty.sty { + let substs = match pat_ty.kind { ty::Adt(_, substs) => substs, _ => bug!("unexpected pattern type {:?}", pat_ty), }; @@ -781,7 +781,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut expected_len = elements.len(); if ddpos.is_some() { // Require known type only when `..` is present. - if let ty::Tuple(ref tys) = self.structurally_resolved_type(span, expected).sty { + if let ty::Tuple(ref tys) = self.structurally_resolved_type(span, expected).kind { expected_len = tys.len(); } } @@ -828,7 +828,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> bool { let tcx = self.tcx; - let (substs, adt) = match adt_ty.sty { + let (substs, adt) = match adt_ty.kind { ty::Adt(adt, substs) => (substs, adt), _ => span_bug!(span, "struct pattern is not an ADT") }; @@ -1066,7 +1066,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // to avoid creating needless variables. This also helps with // the bad interactions of the given hack detailed in (note_1). debug!("check_pat_ref: expected={:?}", expected); - match expected.sty { + match expected.kind { ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty), _ => { let inner_ty = self.next_ty_var( @@ -1114,7 +1114,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let tcx = self.tcx; let expected_ty = self.structurally_resolved_type(span, expected); - let (inner_ty, slice_ty) = match expected_ty.sty { + let (inner_ty, slice_ty) = match expected_ty.kind { ty::Array(inner_ty, size) => { let slice_ty = if let Some(size) = size.try_eval_usize(tcx, self.param_env) { let min_len = before.len() as u64 + after.len() as u64; @@ -1203,8 +1203,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "expected an array or slice, found `{}`", expected_ty ); - if let ty::Ref(_, ty, _) = expected_ty.sty { - if let ty::Array(..) | ty::Slice(..) = ty.sty { + if let ty::Ref(_, ty, _) = expected_ty.kind { + if let ty::Array(..) | ty::Slice(..) = ty.kind { err.help("the semantics of slice patterns changed recently; see issue #62254"); } } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index fc01a820e2359..9ca2a275fcef6 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -623,7 +623,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> { // For overloaded derefs, base_ty is the input to `Deref::deref`, // but it's a reference type uing the same region as the output. let base_ty = self.resolve_expr_type_adjusted(base); - if let ty::Ref(r_ptr, _, _) = base_ty.sty { + if let ty::Ref(r_ptr, _, _) = base_ty.kind { self.mk_subregion_due_to_dereference(expr.span, expr_region, r_ptr); } @@ -722,7 +722,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { fn walk_cast(&mut self, cast_expr: &hir::Expr, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) { debug!("walk_cast(from_ty={:?}, to_ty={:?})", from_ty, to_ty); - match (&from_ty.sty, &to_ty.sty) { + match (&from_ty.kind, &to_ty.kind) { /*From:*/ (&ty::Ref(from_r, from_ty, _), /*To: */ &ty::Ref(to_r, to_ty, _)) => { // Target cannot outlive source, naturally. @@ -756,7 +756,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { fn constrain_callee(&mut self, callee_expr: &hir::Expr) { let callee_ty = self.resolve_node_type(callee_expr.hir_id); - match callee_ty.sty { + match callee_ty.kind { ty::FnDef(..) | ty::FnPtr(_) => {} _ => { // this should not happen, but it does if the program is @@ -968,8 +968,8 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { id: index_expr.hir_id.local_id, data: region::ScopeData::Node, }); - if let ty::Ref(r_ptr, r_ty, _) = indexed_ty.sty { - match r_ty.sty { + if let ty::Ref(r_ptr, r_ty, _) = indexed_ty.kind { + match r_ty.kind { ty::Slice(_) | ty::Str => { self.sub_regions( infer::IndexSlice(index_expr.span), @@ -1164,7 +1164,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { ); let rptr_ty = self.resolve_node_type(id); - if let ty::Ref(r, _, _) = rptr_ty.sty { + if let ty::Ref(r, _, _) = rptr_ty.kind { debug!("rptr_ty={}", rptr_ty); self.link_region(span, r, ty::BorrowKind::from_mutbl(mutbl), cmt_borrowed); } diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 155cabb27a92f..d57fec9947db1 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -95,7 +95,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Extract the type of the closure. let ty = self.node_ty(closure_hir_id); - let (closure_def_id, substs) = match ty.sty { + let (closure_def_id, substs) = match ty.kind { ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)), ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)), ty::Error => { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 265d0676fa8d1..f67a8e9054853 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -366,7 +366,7 @@ fn check_item_type( let mut forbid_unsized = true; if allow_foreign_ty { let tail = fcx.tcx.struct_tail_erasing_lifetimes(item_ty, fcx.param_env); - if let ty::Foreign(_) = tail.sty { + if let ty::Foreign(_) = tail.kind { forbid_unsized = false; } } @@ -511,7 +511,7 @@ fn check_where_clauses<'tcx, 'fcx>( struct CountParams { params: FxHashSet } impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams { fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { - if let ty::Param(param) = t.sty { + if let ty::Param(param) = t.kind { self.params.insert(param.index); } t.super_visit_with(self) @@ -635,7 +635,7 @@ fn check_opaque_types<'fcx, 'tcx>( ty.fold_with(&mut ty::fold::BottomUpFolder { tcx: fcx.tcx, ty_op: |ty| { - if let ty::Opaque(def_id, substs) = ty.sty { + if let ty::Opaque(def_id, substs) = ty.kind { trace!("check_opaque_types: opaque_ty, {:?}, {:?}", def_id, substs); let generics = tcx.generics_of(def_id); // Only check named `impl Trait` types defined in this crate. @@ -646,7 +646,7 @@ fn check_opaque_types<'fcx, 'tcx>( let mut seen: FxHashMap<_, Vec<_>> = FxHashMap::default(); for (subst, param) in substs.iter().zip(&generics.params) { match subst.unpack() { - ty::subst::UnpackedKind::Type(ty) => match ty.sty { + ty::subst::UnpackedKind::Type(ty) => match ty.kind { ty::Param(..) => {} // Prevent `fn foo() -> Foo` from being defining. _ => { diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 1cc71ea5649de..f3ee64e9d1368 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -190,7 +190,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let mut tables = self.fcx.tables.borrow_mut(); // All valid indexing looks like this; might encounter non-valid indexes at this point - if let ty::Ref(_, base_ty, _) = tables.expr_ty_adjusted(&base).sty { + if let ty::Ref(_, base_ty, _) = tables.expr_ty_adjusted(&base).kind { let index_ty = tables.expr_ty_adjusted(&index); let index_ty = self.fcx.resolve_vars_if_possible(&index_ty); @@ -454,7 +454,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let mut skip_add = false; - if let ty::Opaque(defin_ty_def_id, _substs) = definition_ty.sty { + if let ty::Opaque(defin_ty_def_id, _substs) = definition_ty.kind { if def_id == defin_ty_def_id { debug!("Skipping adding concrete definition for opaque type {:?} {:?}", opaque_defn, defin_ty_def_id); diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index a95b9a03dcf77..9054c2b80102a 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -47,7 +47,7 @@ impl<'tcx> Checker<'tcx> { } fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: DefId) { - if let ty::Adt(..) = tcx.type_of(impl_did).sty { + if let ty::Adt(..) = tcx.type_of(impl_did).kind { /* do nothing */ } else { // Destructors only work on nominal types. @@ -186,7 +186,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: DefId) { let cause = ObligationCause::misc(span, impl_hir_id); use ty::TyKind::*; - match (&source.sty, &target.sty) { + match (&source.kind, &target.kind) { (&Ref(r_a, _, mutbl_a), Ref(r_b, _, mutbl_b)) if infcx.at(&cause, param_env).eq(r_a, r_b).is_ok() && mutbl_a == *mutbl_b => (), @@ -367,7 +367,7 @@ pub fn coerce_unsized_info<'tcx>(gcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUn } (mt_a.ty, mt_b.ty, unsize_trait, None) }; - let (source, target, trait_def_id, kind) = match (&source.sty, &target.sty) { + let (source, target, trait_def_id, kind) = match (&source.kind, &target.kind) { (&ty::Ref(r_a, ty_a, mutbl_a), &ty::Ref(r_b, ty_b, mutbl_b)) => { infcx.sub_regions(infer::RelateObjectBound(span), r_b, r_a); let mt_a = ty::TypeAndMut { ty: ty_a, mutbl: mutbl_a }; diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index e7c2126cfd727..d2651317da948 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -57,7 +57,7 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { let def_id = self.tcx.hir().local_def_id(item.hir_id); let self_ty = self.tcx.type_of(def_id); let lang_items = self.tcx.lang_items(); - match self_ty.sty { + match self_ty.kind { ty::Adt(def, _) => { self.check_def_id(item, def.did); } diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 1d0e433f07b3a..a44c475e0f8a9 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -167,7 +167,7 @@ fn check_impl_overlap<'tcx>(tcx: TyCtxt<'tcx>, hir_id: HirId) { tcx.specialization_graph_of(trait_def_id); // check for overlap with the automatic `impl Trait for Trait` - if let ty::Dynamic(ref data, ..) = trait_ref.self_ty().sty { + if let ty::Dynamic(ref data, ..) = trait_ref.self_ty().kind { // This is something like impl Trait1 for Trait2. Illegal // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe. diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 299e18337bd30..8969bf894e0f6 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -102,7 +102,7 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> { if self.tcx.trait_is_auto(trait_def_id) && !trait_def_id.is_local() { let self_ty = trait_ref.self_ty(); - let opt_self_def_id = match self_ty.sty { + let opt_self_def_id = match self_ty.kind { ty::Adt(self_def, _) => Some(self_def.did), ty::Foreign(did) => Some(did), _ => None, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index e6e0cb88fbd23..6a5be9023be72 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1581,7 +1581,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { // their positions. for (idx, subst) in substs.iter().enumerate() { if let UnpackedKind::Type(ty) = subst.unpack() { - if let ty::Param(p) = ty.sty { + if let ty::Param(p) = ty.kind { if index_map.insert(p, idx).is_some() { // There was already an entry for `p`, meaning a generic parameter // was used twice. @@ -1611,11 +1611,11 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { let indices = concrete_type .subst(self.tcx, substs) .walk() - .filter_map(|t| match &t.sty { + .filter_map(|t| match &t.kind { ty::Param(p) => Some(*index_map.get(p).unwrap()), _ => None, }).collect(); - let is_param = |ty: Ty<'_>| match ty.sty { + let is_param = |ty: Ty<'_>| match ty.kind { ty::Param(_) => true, _ => false, }; @@ -1627,7 +1627,7 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } else if let Some((prev_span, prev_ty, ref prev_indices)) = self.found { let mut ty = concrete_type.walk().fuse(); let mut p_ty = prev_ty.walk().fuse(); - let iter_eq = (&mut ty).zip(&mut p_ty).all(|(t, p)| match (&t.sty, &p.sty) { + let iter_eq = (&mut ty).zip(&mut p_ty).all(|(t, p)| match (&t.kind, &p.kind) { // Type parameters are equal to any other type parameter for the purpose of // concrete type equality, as it is possible to obtain the same type just // by passing matching parameters to a function. @@ -2198,7 +2198,7 @@ fn explicit_predicates_of( // That way, `where Ty:` is not a complete noop (see #53696) and `Ty` // is still checked for WF. if bound_pred.bounds.is_empty() { - if let ty::Param(_) = ty.sty { + if let ty::Param(_) = ty.kind { // This is a `where T:`, which can be in the HIR from the // transformation that moves `?Sized` to `T`'s declaration. // We can skip the predicate because type parameters are diff --git a/src/librustc_typeck/constrained_generic_params.rs b/src/librustc_typeck/constrained_generic_params.rs index dd44f86717fe5..31476eb731798 100644 --- a/src/librustc_typeck/constrained_generic_params.rs +++ b/src/librustc_typeck/constrained_generic_params.rs @@ -55,7 +55,7 @@ struct ParameterCollector { impl<'tcx> TypeVisitor<'tcx> for ParameterCollector { fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { - match t.sty { + match t.kind { ty::Projection(..) | ty::Opaque(..) if !self.include_nonconstraining => { // projections are not injective return false; diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 959483e4439ff..2450c807d5493 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -159,7 +159,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) { let main_id = tcx.hir().as_local_hir_id(main_def_id).unwrap(); let main_span = tcx.def_span(main_def_id); let main_t = tcx.type_of(main_def_id); - match main_t.sty { + match main_t.kind { ty::FnDef(..) => { if let Some(Node::Item(it)) = tcx.hir().find(main_id) { if let hir::ItemKind::Fn(.., ref generics, _) = it.node { @@ -224,7 +224,7 @@ fn check_start_fn_ty(tcx: TyCtxt<'_>, start_def_id: DefId) { let start_id = tcx.hir().as_local_hir_id(start_def_id).unwrap(); let start_span = tcx.def_span(start_def_id); let start_t = tcx.type_of(start_def_id); - match start_t.sty { + match start_t.kind { ty::FnDef(..) => { if let Some(Node::Item(it)) = tcx.hir().find(start_id) { if let hir::ItemKind::Fn(.., ref generics, _) = it.node { diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs index 644d723ded5d9..f8d92f625c301 100644 --- a/src/librustc_typeck/outlives/implicit_infer.rs +++ b/src/librustc_typeck/outlives/implicit_infer.rs @@ -123,7 +123,7 @@ fn insert_required_predicates_to_be_wf<'tcx>( explicit_map: &mut ExplicitPredicatesMap<'tcx>, ) { for ty in field_ty.walk() { - match ty.sty { + match ty.kind { // The field is of type &'a T which means that we will have // a predicate requirement of T: 'a (T outlives 'a). // diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 7ed9d6606f646..16d5fde815f6a 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -140,7 +140,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { let id = tcx.hir().as_local_hir_id(def_id).unwrap(); let inferred_start = self.terms_cx.inferred_starts[&id]; let current_item = &CurrentItem { inferred_start }; - match tcx.type_of(def_id).sty { + match tcx.type_of(def_id).kind { ty::Adt(def, _) => { // Not entirely obvious: constraints on structs/enums do not // affect the variance of their type parameters. See discussion @@ -256,7 +256,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { ty, variance); - match ty.sty { + match ty.kind { ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never | ty::Foreign(..) => { // leaf type -- noop diff --git a/src/librustc_typeck/variance/solve.rs b/src/librustc_typeck/variance/solve.rs index 1176c5ebb3d30..fbd476ef832c4 100644 --- a/src/librustc_typeck/variance/solve.rs +++ b/src/librustc_typeck/variance/solve.rs @@ -109,7 +109,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { self.enforce_const_invariance(generics, variances); // Functions are permitted to have unused generic parameters: make those invariant. - if let ty::FnDef(..) = tcx.type_of(def_id).sty { + if let ty::FnDef(..) = tcx.type_of(def_id).kind { for variance in variances.iter_mut() { if *variance == ty::Bivariant { *variance = ty::Invariant; diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 4cd1cc1a1cf50..afed11e7fab26 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -41,7 +41,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { trait_def_id, impl_def_id); let trait_ref = self.cx.tcx.impl_trait_ref(impl_def_id).unwrap(); let may_apply = self.cx.tcx.infer_ctxt().enter(|infcx| { - match trait_ref.self_ty().sty { + match trait_ref.self_ty().kind { ty::Param(_) => {}, _ => return false, } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d1a9b740d62ab..46b71abac5409 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1108,7 +1108,7 @@ fn external_generic_args( None } UnpackedKind::Type(ty) => { - ty_sty = Some(&ty.sty); + ty_sty = Some(&ty.kind); Some(GenericArg::Type(ty.clean(cx))) } UnpackedKind::Const(ct) => Some(GenericArg::Const(ct.clean(cx))), @@ -1124,7 +1124,7 @@ fn external_generic_args( }; let output = None; // FIXME(#20299) return type comes from a projection now - // match types[1].sty { + // match types[1].kind { // ty::Tuple(ref v) if v.is_empty() => None, // -> () // _ => Some(types[1].clean(cx)) // }; @@ -1162,9 +1162,9 @@ impl<'a, 'tcx> Clean for (&'a ty::TraitRef<'tcx>, Vec // collect any late bound regions let mut late_bounds = vec![]; for ty_s in trait_ref.input_types().skip(1) { - if let ty::Tuple(ts) = ty_s.sty { + if let ty::Tuple(ts) = ty_s.kind { for &ty_s in ts { - if let ty::Ref(ref reg, _, _) = ty_s.expect_ty().sty { + if let ty::Ref(ref reg, _, _) = ty_s.expect_ty().kind { if let &ty::RegionKind::ReLateBound(..) = *reg { debug!(" hit an ReLateBound {:?}", reg); if let Some(Lifetime(name)) = reg.clean(cx) { @@ -1705,15 +1705,15 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics, let mut projection = None; let param_idx = (|| { if let Some(trait_ref) = p.to_opt_poly_trait_ref() { - if let ty::Param(param) = trait_ref.self_ty().sty { + if let ty::Param(param) = trait_ref.self_ty().kind { return Some(param.index); } } else if let Some(outlives) = p.to_opt_type_outlives() { - if let ty::Param(param) = outlives.skip_binder().0.sty { + if let ty::Param(param) = outlives.skip_binder().0.kind { return Some(param.index); } } else if let ty::Predicate::Projection(p) = p { - if let ty::Param(param) = p.skip_binder().projection_ty.self_ty().sty { + if let ty::Param(param) = p.skip_binder().projection_ty.self_ty().kind { projection = Some(p); return Some(param.index); } @@ -2380,7 +2380,7 @@ impl Clean for ty::AssocItem { let self_arg_ty = *sig.input(0).skip_binder(); if self_arg_ty == self_ty { decl.inputs.values[0].type_ = Generic(String::from("Self")); - } else if let ty::Ref(_, ty, _) = self_arg_ty.sty { + } else if let ty::Ref(_, ty, _) = self_arg_ty.kind { if ty == self_ty { match decl.inputs.values[0].type_ { BorrowedRef{ref mut type_, ..} => { @@ -3000,7 +3000,7 @@ impl Clean for hir::Ty { TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => { let mut res = Res::Err; let ty = hir_ty_to_ty(cx.tcx, self); - if let ty::Projection(proj) = ty.sty { + if let ty::Projection(proj) = ty.kind { res = Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id); } let trait_path = hir::Path { @@ -3040,7 +3040,7 @@ impl Clean for hir::Ty { impl<'tcx> Clean for Ty<'tcx> { fn clean(&self, cx: &DocContext<'_>) -> Type { debug!("cleaning type: {:?}", self); - match self.sty { + match self.kind { ty::Never => Never, ty::Bool => Primitive(PrimitiveType::Bool), ty::Char => Primitive(PrimitiveType::Char), diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index b67f39d328015..9186ed514202f 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -155,7 +155,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { }; Ok((ty_res, Some(format!("{}.{}", out, item_name)))) } else { - match cx.tcx.type_of(did).sty { + match cx.tcx.type_of(did).kind { ty::Adt(def, _) => { if let Some(item) = if def.is_enum() { def.all_fields().find(|item| item.ident.name == item_name) From bd5adc51fb6989435d39b3f4d484430c6714d762 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 16 Sep 2019 19:11:57 +0100 Subject: [PATCH 186/413] Rename surviving uses of `sty` --- .../traits/specialize/specialization_graph.rs | 18 +++++++++--------- src/librustc/ty/context.rs | 4 ++-- src/librustc/ty/structural_impls.rs | 8 ++++---- .../borrow_check/nll/type_check/mod.rs | 16 ++++++++-------- src/librustc_typeck/check/coercion.rs | 9 ++++----- .../internal-lints/ty_tykind_usage.rs | 8 ++++---- .../internal-lints/ty_tykind_usage.stderr | 4 ++-- 7 files changed, 33 insertions(+), 34 deletions(-) diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index 885d4b4cb0269..8cbadebaea5a5 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -85,11 +85,11 @@ impl<'tcx> Children { /// Insert an impl into this set of children without comparing to any existing impls. fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); - if let Some(sty) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) { - debug!("insert_blindly: impl_def_id={:?} sty={:?}", impl_def_id, sty); - self.nonblanket_impls.entry(sty).or_default().push(impl_def_id) + if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) { + debug!("insert_blindly: impl_def_id={:?} st={:?}", impl_def_id, st); + self.nonblanket_impls.entry(st).or_default().push(impl_def_id) } else { - debug!("insert_blindly: impl_def_id={:?} sty=None", impl_def_id); + debug!("insert_blindly: impl_def_id={:?} st=None", impl_def_id); self.blanket_impls.push(impl_def_id) } } @@ -100,11 +100,11 @@ impl<'tcx> Children { fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); let vec: &mut Vec; - if let Some(sty) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) { - debug!("remove_existing: impl_def_id={:?} sty={:?}", impl_def_id, sty); - vec = self.nonblanket_impls.get_mut(&sty).unwrap(); + if let Some(st) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) { + debug!("remove_existing: impl_def_id={:?} st={:?}", impl_def_id, st); + vec = self.nonblanket_impls.get_mut(&st).unwrap(); } else { - debug!("remove_existing: impl_def_id={:?} sty=None", impl_def_id); + debug!("remove_existing: impl_def_id={:?} st=None", impl_def_id); vec = &mut self.blanket_impls; } @@ -130,7 +130,7 @@ impl<'tcx> Children { ); let possible_siblings = match simplified_self { - Some(sty) => PotentialSiblings::Filtered(self.filtered(sty)), + Some(st) => PotentialSiblings::Filtered(self.filtered(st)), None => PotentialSiblings::Unfiltered(self.iter()), }; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 371ce885ce2ea..c08f250f3dcee 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -890,7 +890,7 @@ EnumLiftImpl! { impl<'tcx> CommonTypes<'tcx> { fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> { - let mk = |sty| interners.intern_ty(sty); + let mk = |ty| interners.intern_ty(ty); CommonTypes { unit: mk(Tuple(List::empty())), @@ -2080,7 +2080,7 @@ impl<'tcx, T: 'tcx+?Sized> Clone for Interned<'tcx, T> { } impl<'tcx, T: 'tcx+?Sized> Copy for Interned<'tcx, T> {} -// N.B., an `Interned` compares and hashes as a sty. +// N.B., an `Interned` compares and hashes as a `TyKind`. impl<'tcx> PartialEq for Interned<'tcx, TyS<'tcx>> { fn eq(&self, other: &Interned<'tcx, TyS<'tcx>>) -> bool { self.0.kind == other.0.kind diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 72e1bd33c6a81..42d632d120ea1 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -1023,7 +1023,7 @@ impl<'tcx> TypeFoldable<'tcx> for interpret::GlobalId<'tcx> { impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { fn super_fold_with>(&self, folder: &mut F) -> Self { - let sty = match self.kind { + let kind = match self.kind { ty::RawPtr(tm) => ty::RawPtr(tm.fold_with(folder)), ty::Array(typ, sz) => ty::Array(typ.fold_with(folder), sz.fold_with(folder)), ty::Slice(typ) => ty::Slice(typ.fold_with(folder)), @@ -1064,13 +1064,13 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::Bound(..) | ty::Placeholder(..) | ty::Never | - ty::Foreign(..) => return self + ty::Foreign(..) => return self, }; - if self.kind == sty { + if self.kind == kind { self } else { - folder.tcx().mk_ty(sty) + folder.tcx().mk_ty(kind) } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 4996ea83ae04e..eadc58cc80027 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -424,15 +424,15 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { let mut place_ty = match &place.base { PlaceBase::Local(index) => PlaceTy::from_ty(self.body.local_decls[*index].ty), - PlaceBase::Static(box Static { kind, ty: sty, def_id }) => { - let sty = self.sanitize_type(place, sty); + PlaceBase::Static(box Static { kind, ty, def_id }) => { + let san_ty = self.sanitize_type(place, ty); let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>, place: &Place<'tcx>, ty, - sty| { + san_ty| { if let Err(terr) = verifier.cx.eq_types( - sty, + san_ty, ty, location.to_locations(), ConstraintCategory::Boring, @@ -442,7 +442,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { place, "bad promoted type ({:?}: {:?}): {:?}", ty, - sty, + san_ty, terr ); }; @@ -454,17 +454,17 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { self.sanitize_promoted(promoted_body, location); let promoted_ty = promoted_body.return_ty(); - check_err(self, place, promoted_ty, sty); + check_err(self, place, promoted_ty, san_ty); } } StaticKind::Static => { let ty = self.tcx().type_of(*def_id); let ty = self.cx.normalize(ty, location); - check_err(self, place, ty, sty); + check_err(self, place, ty, san_ty); } } - PlaceTy::from_ty(sty) + PlaceTy::from_ty(san_ty) } }; diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index e507fa31435ac..564a0eac75539 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -566,15 +566,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let obligation = queue.remove(0); debug!("coerce_unsized resolve step: {:?}", obligation); let trait_ref = match obligation.predicate { - ty::Predicate::Trait(ref tr) if traits.contains(&tr.def_id()) => { - if unsize_did == tr.def_id() { - let sty = &tr.skip_binder().input_types().nth(1).unwrap().kind; - if let ty::Tuple(..) = sty { + ty::Predicate::Trait(ref t) if traits.contains(&t.def_id()) => { + if unsize_did == t.def_id() { + if let ty::Tuple(..) = &t.skip_binder().input_types().nth(1).unwrap().kind { debug!("coerce_unsized: found unsized tuple coercion"); has_unsized_tuple_coercion = true; } } - tr.clone() + t.clone() } _ => { coercion.obligations.push(obligation); diff --git a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs index c6bd122f4e548..f716a78a031f2 100644 --- a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs +++ b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs @@ -8,9 +8,9 @@ use rustc::ty::{self, Ty, TyKind}; #[deny(rustc::usage_of_ty_tykind)] fn main() { - let sty = TyKind::Bool; //~ ERROR usage of `ty::TyKind::` + let kind = TyKind::Bool; //~ ERROR usage of `ty::TyKind::` - match sty { + match kind { TyKind::Bool => (), //~ ERROR usage of `ty::TyKind::` TyKind::Char => (), //~ ERROR usage of `ty::TyKind::` TyKind::Int(..) => (), //~ ERROR usage of `ty::TyKind::` @@ -41,9 +41,9 @@ fn main() { TyKind::Error => (), //~ ERROR usage of `ty::TyKind::` } - if let ty::Int(int_ty) = sty {} + if let ty::Int(int_ty) = kind {} - if let TyKind::Int(int_ty) = sty {} //~ ERROR usage of `ty::TyKind::` + if let TyKind::Int(int_ty) = kind {} //~ ERROR usage of `ty::TyKind::` fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {} //~ ERROR usage of `ty::TyKind` } diff --git a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr index 8add4252c4103..a5c9ed3478cf4 100644 --- a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr +++ b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr @@ -1,7 +1,7 @@ error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:11:15 | -LL | let sty = TyKind::Bool; +LL | let kind = TyKind::Bool; | ^^^^^^ help: try using ty:: directly: `ty` | note: lint level defined here @@ -181,7 +181,7 @@ LL | TyKind::Error => (), error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:46:12 | -LL | if let TyKind::Int(int_ty) = sty {} +LL | if let TyKind::Int(int_ty) = kind {} | ^^^^^^ help: try using ty:: directly: `ty` error: usage of `ty::TyKind` From 93df1bb517e32163c78c776ce7bd89e3cb2db116 Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 25 Sep 2019 15:57:54 +0100 Subject: [PATCH 187/413] Fix rebase --- src/librustc/infer/mod.rs | 2 +- src/librustc/traits/error_reporting.rs | 2 +- src/librustc/ty/error.rs | 4 ++-- src/librustc_mir/const_eval.rs | 2 +- src/librustc_typeck/check/pat.rs | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index b715598ef80f0..c1782f53f0d2f 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1604,7 +1604,7 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> { // are extremely hot. #[inline(always)] pub fn shallow_resolve_changed(&mut self, typ: Ty<'tcx>) -> bool { - match typ.sty { + match typ.kind { ty::Infer(ty::TyVar(v)) => { use self::type_variable::TypeVariableValue; diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 16c808edb6ef4..0683940af985e 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1463,7 +1463,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ty::Predicate::Trait(ref data) => { let trait_ref = data.to_poly_trait_ref(); let self_ty = trait_ref.self_ty(); - debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.sty, trait_ref); + debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref); if predicate.references_error() { return; diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 8b8708844979a..d12039de3136e 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -373,9 +373,9 @@ impl Trait for X { debug!( "note_and_explain_type_err expected={:?} ({:?}) found={:?} ({:?})", values.expected, - values.expected.sty, + values.expected.kind, values.found, - values.found.sty, + values.found.kind, ); }, CyclicTy(ty) => { diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index d1e00253a98de..ca238867421ab 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -608,7 +608,7 @@ pub fn const_eval_provider<'tcx>( // Catch such calls and evaluate them instead of trying to load a constant's MIR. if let ty::InstanceDef::Intrinsic(def_id) = key.value.instance.def { let ty = key.value.instance.ty(tcx); - let substs = match ty.sty { + let substs = match ty.kind { ty::FnDef(_, substs) => substs, _ => bug!("intrinsic with type {:?}", ty), }; diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index b9311f6b512c5..550ea0bf2da5f 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -718,10 +718,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // More generally, the expected type wants a tuple variant with one field of an // N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern // with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`. - let missing_parenthesis = match expected.sty { + let missing_parenthesis = match expected.kind { ty::Adt(_, substs) if fields.len() == 1 => { let field_ty = fields[0].ty(self.tcx, substs); - match field_ty.sty { + match field_ty.kind { ty::Tuple(_) => field_ty.tuple_fields().count() == subpats.len(), _ => false, } From d047c4257c269865086d1e0b201dbaa3c2ae258e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 25 Sep 2019 11:15:21 -0700 Subject: [PATCH 188/413] Update cargo 4 commits in aa6b7e01abce30091cc594cb23a15c46cead6e24..ab6fa8908c9b6c8f7e2249231c395eebfbc49891 2019-09-24 17:19:12 +0000 to 2019-09-25 17:00:56 +0000 - Fix macOS collection of CPU data (rust-lang/cargo#7429) - Don't ever capture CPU state if timings are disabled (rust-lang/cargo#7428) - Change build-std to use --sysroot (rust-lang/cargo#7421) - set -Zmtime_on_use from config or ENV (rust-lang/cargo#7411) --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index aa6b7e01abce3..ab6fa8908c9b6 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit aa6b7e01abce30091cc594cb23a15c46cead6e24 +Subproject commit ab6fa8908c9b6c8f7e2249231c395eebfbc49891 From 2cb460e6259af63924a719beaf91c5804dd0a789 Mon Sep 17 00:00:00 2001 From: AnthonyMikh Date: Wed, 25 Sep 2019 22:55:04 +0300 Subject: [PATCH 189/413] Use `saturating_sub` where applicable --- src/librustc_errors/emitter.rs | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 2a89c94652a24..c5b03acb622f6 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -99,8 +99,8 @@ impl Margin { // ``` let mut m = Margin { - whitespace_left: if whitespace_left >= 6 { whitespace_left - 6 } else { 0 }, - span_left: if span_left >= 6 { span_left - 6 } else { 0 }, + whitespace_left: whitespace_left.saturating_sub(6), + span_left: span_left.saturating_sub(6), span_right: span_right + 6, computed_left: 0, computed_right: 0, @@ -167,7 +167,7 @@ impl Margin { } fn right(&self, line_len: usize) -> usize { - if max(line_len, self.computed_left) - self.computed_left <= self.column_width { + if line_len.saturating_sub(self.computed_left) <= self.column_width { line_len } else if self.computed_right > line_len { line_len @@ -941,17 +941,9 @@ impl EmitterWriter { Style::LabelSecondary }; let (pos, col) = if pos == 0 { - (pos + 1, if annotation.end_col + 1 > left { - annotation.end_col + 1 - left - } else { - 0 - }) + (pos + 1, (annotation.end_col + 1).saturating_sub(left)) } else { - (pos + 2, if annotation.start_col > left { - annotation.start_col - left - } else { - 0 - }) + (pos + 2, annotation.start_col.saturating_sub(left)) }; if let Some(ref label) = annotation.label { buffer.puts(line_offset + pos, code_offset + col, &label, style); @@ -991,11 +983,7 @@ impl EmitterWriter { for p in annotation.start_col..annotation.end_col { buffer.putc( line_offset + 1, - if code_offset + p > left { - code_offset + p - left - } else { - 0 - }, + (code_offset + p).saturating_sub(left), underline, style, ); From e9a93be53a6ccec5ba76f17333acf3c198313c61 Mon Sep 17 00:00:00 2001 From: AnthonyMikh Date: Wed, 25 Sep 2019 23:08:09 +0300 Subject: [PATCH 190/413] Use `max` instead of `if`s --- src/librustc_errors/emitter.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index c5b03acb622f6..45c3dd8f4d825 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -169,10 +169,8 @@ impl Margin { fn right(&self, line_len: usize) -> usize { if line_len.saturating_sub(self.computed_left) <= self.column_width { line_len - } else if self.computed_right > line_len { - line_len } else { - self.computed_right + min(line_len, self.computed_right) } } } @@ -797,9 +795,7 @@ impl EmitterWriter { } } } - if line_len < p { - line_len = p; - } + line_len = max(line_len, p); } if line_len != 0 { @@ -1772,9 +1768,7 @@ impl FileWithAnnotatedLines { let mut max_depth = 0; // max overlapping multiline spans for (file, ann) in multiline_annotations { - if ann.depth > max_depth { - max_depth = ann.depth; - } + max_depth = max(max_depth, ann.depth); let mut end_ann = ann.as_end(); if !ann.overlaps_exactly { // avoid output like From 4fc5650d17794c00fbf03597b35979de7094d386 Mon Sep 17 00:00:00 2001 From: AnthonyMikh Date: Wed, 25 Sep 2019 23:13:19 +0300 Subject: [PATCH 191/413] Simplify Unicode-aware trimming --- src/librustc_errors/emitter.rs | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 45c3dd8f4d825..151c06ddbbd4c 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -529,18 +529,21 @@ impl EmitterWriter { let left = margin.left(line_len); let right = margin.right(line_len); // On long lines, we strip the source line, accounting for unicode. - let mut taken = 0; - let code: String = source_string.chars().skip(left).take_while(|ch| { - // Make sure that the trimming on the right will fall within the terminal width. - // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` is. - // For now, just accept that sometimes the code line will be longer than desired. - let next = unicode_width::UnicodeWidthChar::width(*ch).unwrap_or(1); - if taken + next > right - left { - return false; - } - taken += next; - true - }).collect(); + // Make sure that the trimming on the right will fall within the terminal width. + // FIXME: `unicode_width` sometimes disagrees with terminals on how wide a `char` is. + // For now, just accept that sometimes the code line will be longer than desired. + let code: String = source_string.chars().skip(left) + .map(|ch| { + let width = unicode_width::UnicodeWidthChar::width(*ch).unwrap_or(1); + (width, ch) + }) + .scan(0, |len, (width, ch)| { + *len += width; + Some(*len, ch) + }) + .take_while(|&(prefix_len, _ch)| prefix_len <= right - left) + .map(|(_prefix_len, ch)| ch) + .collect(); buffer.puts(line_offset, code_offset, &code, Style::Quotation); if margin.was_cut_left() { // We have stripped some code/whitespace from the beginning, make it clear. From e70724c23bd2bd5cfbbac784d103f2a61a40284f Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Tue, 24 Sep 2019 21:16:09 +0300 Subject: [PATCH 192/413] address rebase damage --- src/libcore/convert.rs | 2 +- .../traits/reservation-impls/reservation-impl-no-use.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs index f639309db8791..3cd2337ee59a5 100644 --- a/src/libcore/convert.rs +++ b/src/libcore/convert.rs @@ -560,7 +560,7 @@ impl From for T { /// /// [#64715]: https://github.com/rust-lang/rust/issues/64715 #[stable(feature = "convert_infallible", since = "1.34.0")] -#[cfg(not(boostrap_stdarch_ignore_this))] +#[cfg(not(bootstrap))] #[rustc_reservation_impl="permitting this impl would forbid us from adding \ `impl From for T` later; see rust-lang/rust#64715 for details"] impl From for T { diff --git a/src/test/ui/traits/reservation-impls/reservation-impl-no-use.stderr b/src/test/ui/traits/reservation-impls/reservation-impl-no-use.stderr index 8a86f53086dd5..0cd56b978f10c 100644 --- a/src/test/ui/traits/reservation-impls/reservation-impl-no-use.stderr +++ b/src/test/ui/traits/reservation-impls/reservation-impl-no-use.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `(): MyTrait` is not satisfied - --> $DIR/reservation-impl-no-use.rs:12:5 + --> $DIR/reservation-impl-no-use.rs:12:26 | LL | trait MyTrait { fn foo(&self); } | -------------- required by `MyTrait::foo` ... LL | <() as MyTrait>::foo(&()); - | ^^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `()` + | ^^^ the trait `MyTrait` is not implemented for `()` | = help: the following implementations were found: <() as MyTrait> From d6327e8f12cc51254d62e6755f67ea580fc4dd21 Mon Sep 17 00:00:00 2001 From: AnthonyMikh Date: Wed, 25 Sep 2019 23:23:19 +0300 Subject: [PATCH 193/413] Use map + sum instead of fold for computing Unicode width --- src/librustc_errors/emitter.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 151c06ddbbd4c..17a5fac6da75e 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -594,9 +594,9 @@ impl EmitterWriter { let left = margin.left(source_string.len()); // Left trim // Account for unicode characters of width !=0 that were removed. - let left = source_string.chars().take(left).fold(0, |acc, ch| { - acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1) - }); + let left = source_string.chars().take(left) + .map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1)) + .sum(); self.draw_line( buffer, @@ -1512,9 +1512,9 @@ impl EmitterWriter { .saturating_sub(part.snippet.trim_start().len()); // ...or trailing spaces. Account for substitutions containing unicode // characters. - let sub_len = part.snippet.trim().chars().fold(0, |acc, ch| { - acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1) - }); + let sub_len = part.snippet.trim().chars() + .map(|ch| unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1)) + .sum(); let underline_start = (span_start_pos + start) as isize + offset; let underline_end = (span_start_pos + start + sub_len) as isize + offset; @@ -1535,9 +1535,9 @@ impl EmitterWriter { } // length of the code after substitution - let full_sub_len = part.snippet.chars().fold(0, |acc, ch| { - acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1) as isize - }); + let full_sub_len = part.snippet.chars() + .map(|ch| acc + unicode_width::UnicodeWidthChar::width(ch).unwrap_or(1)) + .sum() as isize; // length of the code to be substituted let snippet_len = span_end_pos as isize - span_start_pos as isize; From aef169b4e637fe417f05fa50450b90e403023a5f Mon Sep 17 00:00:00 2001 From: AnthonyMikh Date: Wed, 25 Sep 2019 23:41:27 +0300 Subject: [PATCH 194/413] Use Option::map_or where applicable --- src/librustc_errors/emitter.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 17a5fac6da75e..61bd4899f3c54 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -764,11 +764,7 @@ impl EmitterWriter { annotations_position.push((p, annotation)); for (j, next) in annotations.iter().enumerate() { if j > i { - let l = if let Some(ref label) = next.label { - label.len() + 2 - } else { - 0 - }; + let l = next.label.map_or(0, |label| label.len() + 2); if (overlaps(next, annotation, l) // Do not allow two labels to be in the same // line if they overlap including padding, to // avoid situations like: @@ -1311,13 +1307,12 @@ impl EmitterWriter { for line in &annotated_file.lines { max_line_len = max(max_line_len, annotated_file.file .get_line(line.line_index - 1) - .map(|s| s.len()) - .unwrap_or(0)); + .map_or(0, |s| s.len()); for ann in &line.annotations { span_right_margin = max(span_right_margin, ann.start_col); span_right_margin = max(span_right_margin, ann.end_col); // FIXME: account for labels not in the same line - let label_right = ann.label.as_ref().map(|l| l.len() + 1).unwrap_or(0); + let label_right = ann.label.as_ref().map_or(0, |l| l.len() + 1); label_right_margin = max(label_right_margin, ann.end_col + label_right); } } From 9b447e2f9fb9b0d3366de90b2de72541b195e99d Mon Sep 17 00:00:00 2001 From: AnthonyMikh Date: Wed, 25 Sep 2019 23:46:33 +0300 Subject: [PATCH 195/413] Unify order of variables in chained comparison --- src/librustc_errors/emitter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 61bd4899f3c54..362e28661d919 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -125,7 +125,7 @@ impl Margin { } else { self.computed_right }; - right < line_len && line_len > self.computed_left + self.column_width + right < line_len && self.computed_left + self.column_width < line_len } fn compute(&mut self, max_line_len: usize) { From b8a040fc5f5edc41af0ccb070239898c0c5d5484 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 25 Sep 2019 13:14:43 -0400 Subject: [PATCH 196/413] Remove tx_to_llvm_workers from TyCtxt This can be kept within the codegen backend crates entirely --- src/librustc/ty/context.rs | 11 -------- src/librustc_codegen_llvm/base.rs | 8 ++++-- src/librustc_codegen_llvm/lib.rs | 13 ++++++---- src/librustc_codegen_ssa/back/write.rs | 23 +++++++++-------- src/librustc_codegen_ssa/base.rs | 25 ++++++------------- src/librustc_codegen_ssa/traits/backend.rs | 8 +++++- src/librustc_codegen_utils/codegen_backend.rs | 2 -- src/librustc_interface/passes.rs | 6 +---- src/librustc_interface/queries.rs | 15 ----------- .../hotplug_codegen_backend/the_backend.rs | 1 - 10 files changed, 42 insertions(+), 70 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index a25ef21d6978f..d45b294690c2b 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -64,7 +64,6 @@ use std::fmt; use std::mem; use std::ops::{Deref, Bound}; use std::iter; -use std::sync::mpsc; use std::sync::Arc; use rustc_target::spec::abi; use rustc_macros::HashStable; @@ -1064,14 +1063,6 @@ pub struct GlobalCtxt<'tcx> { layout_interner: ShardedHashMap<&'tcx LayoutDetails, ()>, - /// A general purpose channel to throw data out the back towards LLVM worker - /// threads. - /// - /// This is intended to only get used during the codegen phase of the compiler - /// when satisfying the query for a particular codegen unit. Internally in - /// the query it'll send data along this channel to get processed later. - pub tx_to_llvm_workers: Lock>>, - output_filenames: Arc, } @@ -1184,7 +1175,6 @@ impl<'tcx> TyCtxt<'tcx> { hir: hir_map::Map<'tcx>, on_disk_query_result_cache: query::OnDiskCache<'tcx>, crate_name: &str, - tx: mpsc::Sender>, output_filenames: &OutputFilenames, ) -> GlobalCtxt<'tcx> { let data_layout = TargetDataLayout::parse(&s.target.target).unwrap_or_else(|err| { @@ -1291,7 +1281,6 @@ impl<'tcx> TyCtxt<'tcx> { stability_interner: Default::default(), allocation_interner: Default::default(), alloc_map: Lock::new(interpret::AllocMap::new()), - tx_to_llvm_workers: Lock::new(tx), output_filenames: Arc::new(output_filenames.clone()), } } diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 21c19e167cfbe..5758cdbebf7d7 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -103,7 +103,11 @@ pub fn iter_globals(llmod: &'ll llvm::Module) -> ValueIter<'ll> { } } -pub fn compile_codegen_unit(tcx: TyCtxt<'tcx>, cgu_name: InternedString) { +pub fn compile_codegen_unit( + tcx: TyCtxt<'tcx>, + cgu_name: InternedString, + tx_to_llvm_workers: &std::sync::mpsc::Sender>, +) { let start_time = Instant::now(); let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx); @@ -121,7 +125,7 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'tcx>, cgu_name: InternedString) { let cost = time_to_codegen.as_secs() * 1_000_000_000 + time_to_codegen.subsec_nanos() as u64; - submit_codegened_module_to_llvm(&LlvmCodegenBackend(()), tcx, module, cost); + submit_codegened_module_to_llvm(&LlvmCodegenBackend(()), tx_to_llvm_workers, module, cost); fn module_codegen( tcx: TyCtxt<'_>, diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 34e39af3c39fc..2a63011c2f545 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -52,7 +52,7 @@ use syntax::ext::allocator::AllocatorKind; use syntax_pos::symbol::InternedString; pub use llvm_util::target_features; use std::any::Any; -use std::sync::{mpsc, Arc}; +use std::sync::Arc; use std::ffi::CStr; use rustc::dep_graph::DepGraph; @@ -122,8 +122,12 @@ impl ExtraBackendMethods for LlvmCodegenBackend { ) { unsafe { allocator::codegen(tcx, mods, kind) } } - fn compile_codegen_unit(&self, tcx: TyCtxt<'_>, cgu_name: InternedString) { - base::compile_codegen_unit(tcx, cgu_name); + fn compile_codegen_unit( + &self, tcx: TyCtxt<'_>, + cgu_name: InternedString, + tx: &std::sync::mpsc::Sender>, + ) { + base::compile_codegen_unit(tcx, cgu_name, tx); } fn target_machine_factory( &self, @@ -284,10 +288,9 @@ impl CodegenBackend for LlvmCodegenBackend { tcx: TyCtxt<'tcx>, metadata: EncodedMetadata, need_metadata_module: bool, - rx: mpsc::Receiver>, ) -> Box { box rustc_codegen_ssa::base::codegen_crate( - LlvmCodegenBackend(()), tcx, metadata, need_metadata_module, rx) + LlvmCodegenBackend(()), tcx, metadata, need_metadata_module) } fn join_codegen_and_link( diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 1a2c23ae0d4f7..3c5fbfd0f866f 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -376,9 +376,9 @@ pub fn start_async_codegen( backend: B, tcx: TyCtxt<'_>, metadata: EncodedMetadata, - coordinator_receive: Receiver>, total_cgus: usize, ) -> OngoingCodegen { + let (coordinator_send, coordinator_receive) = channel(); let sess = tcx.sess; let crate_name = tcx.crate_name(LOCAL_CRATE); let crate_hash = tcx.crate_hash(LOCAL_CRATE); @@ -500,7 +500,8 @@ pub fn start_async_codegen( sess.jobserver.clone(), Arc::new(modules_config), Arc::new(metadata_config), - Arc::new(allocator_config)); + Arc::new(allocator_config), + coordinator_send.clone()); OngoingCodegen { backend, @@ -511,7 +512,7 @@ pub fn start_async_codegen( linker_info, crate_info, - coordinator_send: tcx.tx_to_llvm_workers.lock().clone(), + coordinator_send, codegen_worker_receive, shared_emitter_main, future: coordinator_thread, @@ -1005,8 +1006,9 @@ fn start_executing_work( modules_config: Arc, metadata_config: Arc, allocator_config: Arc, + tx_to_llvm_workers: Sender>, ) -> thread::JoinHandle> { - let coordinator_send = tcx.tx_to_llvm_workers.lock().clone(); + let coordinator_send = tx_to_llvm_workers; let sess = tcx.sess; // Compute the set of symbols we need to retain when doing LTO (if we need to) @@ -1857,7 +1859,7 @@ impl OngoingCodegen { // These are generally cheap and won't throw off scheduling. let cost = 0; - submit_codegened_module_to_llvm(&self.backend, tcx, module, cost); + submit_codegened_module_to_llvm(&self.backend, &self.coordinator_send, module, cost); } pub fn codegen_finished(&self, tcx: TyCtxt<'_>) { @@ -1899,12 +1901,12 @@ impl OngoingCodegen { pub fn submit_codegened_module_to_llvm( _backend: &B, - tcx: TyCtxt<'_>, + tx_to_llvm_workers: &Sender>, module: ModuleCodegen, cost: u64, ) { let llvm_work_item = WorkItem::Optimize(module); - drop(tcx.tx_to_llvm_workers.lock().send(Box::new(Message::CodegenDone:: { + drop(tx_to_llvm_workers.send(Box::new(Message::CodegenDone:: { llvm_work_item, cost, }))); @@ -1912,11 +1914,11 @@ pub fn submit_codegened_module_to_llvm( pub fn submit_post_lto_module_to_llvm( _backend: &B, - tcx: TyCtxt<'_>, + tx_to_llvm_workers: &Sender>, module: CachedModuleCodegen, ) { let llvm_work_item = WorkItem::CopyPostLtoArtifacts(module); - drop(tcx.tx_to_llvm_workers.lock().send(Box::new(Message::CodegenDone:: { + drop(tx_to_llvm_workers.send(Box::new(Message::CodegenDone:: { llvm_work_item, cost: 0, }))); @@ -1925,6 +1927,7 @@ pub fn submit_post_lto_module_to_llvm( pub fn submit_pre_lto_module_to_llvm( _backend: &B, tcx: TyCtxt<'_>, + tx_to_llvm_workers: &Sender>, module: CachedModuleCodegen, ) { let filename = pre_lto_bitcode_filename(&module.name); @@ -1939,7 +1942,7 @@ pub fn submit_pre_lto_module_to_llvm( }) }; // Schedule the module to be loaded - drop(tcx.tx_to_llvm_workers.lock().send(Box::new(Message::AddImportOnlyModule:: { + drop(tx_to_llvm_workers.send(Box::new(Message::AddImportOnlyModule:: { module_data: SerializedModule::FromUncompressedFile(mmap), work_product: module.source, }))); diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 98d3022a4185d..4f9e7d398a370 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -43,11 +43,9 @@ use crate::mir; use crate::traits::*; -use std::any::Any; use std::cmp; use std::ops::{Deref, DerefMut}; use std::time::{Instant, Duration}; -use std::sync::mpsc; use syntax_pos::Span; use syntax::attr; use rustc::hir; @@ -482,19 +480,13 @@ pub fn codegen_crate( tcx: TyCtxt<'tcx>, metadata: EncodedMetadata, need_metadata_module: bool, - rx: mpsc::Receiver>, ) -> OngoingCodegen { check_for_rustc_errors_attr(tcx); // Skip crate items and just output metadata in -Z no-codegen mode. if tcx.sess.opts.debugging_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() { - let ongoing_codegen = start_async_codegen( - backend, - tcx, - metadata, - rx, - 1); + let ongoing_codegen = start_async_codegen(backend, tcx, metadata, 1); ongoing_codegen.codegen_finished(tcx); @@ -523,12 +515,7 @@ pub fn codegen_crate( } } - let ongoing_codegen = start_async_codegen( - backend.clone(), - tcx, - metadata, - rx, - codegen_units.len()); + let ongoing_codegen = start_async_codegen(backend.clone(), tcx, metadata, codegen_units.len()); let ongoing_codegen = AbortCodegenOnDrop::(Some(ongoing_codegen)); // Codegen an allocator shim, if necessary. @@ -614,20 +601,22 @@ pub fn codegen_crate( CguReuse::No => { tcx.sess.profiler(|p| p.start_activity(format!("codegen {}", cgu.name()))); let start_time = Instant::now(); - backend.compile_codegen_unit(tcx, *cgu.name()); + backend.compile_codegen_unit(tcx, *cgu.name(), &ongoing_codegen.coordinator_send); total_codegen_time += start_time.elapsed(); tcx.sess.profiler(|p| p.end_activity(format!("codegen {}", cgu.name()))); false } CguReuse::PreLto => { - submit_pre_lto_module_to_llvm(&backend, tcx, CachedModuleCodegen { + submit_pre_lto_module_to_llvm(&backend, tcx, &ongoing_codegen.coordinator_send, + CachedModuleCodegen { name: cgu.name().to_string(), source: cgu.work_product(tcx), }); true } CguReuse::PostLto => { - submit_post_lto_module_to_llvm(&backend, tcx, CachedModuleCodegen { + submit_post_lto_module_to_llvm(&backend, &ongoing_codegen.coordinator_send, + CachedModuleCodegen { name: cgu.name().to_string(), source: cgu.work_product(tcx), }); diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs index 9fbb44dcc9959..cb197f51460a1 100644 --- a/src/librustc_codegen_ssa/traits/backend.rs +++ b/src/librustc_codegen_ssa/traits/backend.rs @@ -8,6 +8,7 @@ use rustc::session::{Session, config}; use rustc::ty::TyCtxt; use rustc_codegen_utils::codegen_backend::CodegenBackend; use std::sync::Arc; +use std::sync::mpsc; use syntax::ext::allocator::AllocatorKind; use syntax_pos::symbol::InternedString; @@ -44,7 +45,12 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se mods: &mut Self::Module, kind: AllocatorKind, ); - fn compile_codegen_unit(&self, tcx: TyCtxt<'_>, cgu_name: InternedString); + fn compile_codegen_unit( + &self, + tcx: TyCtxt<'_>, + cgu_name: InternedString, + tx_to_llvm_workers: &mpsc::Sender>, + ); // If find_features is true this won't access `sess.crate_types` by assuming // that `is_pie_binary` is false. When we discover LLVM target features // `sess.crate_types` is uninitialized so we cannot access it. diff --git a/src/librustc_codegen_utils/codegen_backend.rs b/src/librustc_codegen_utils/codegen_backend.rs index 262cfb1658ef9..2e3af8431eed0 100644 --- a/src/librustc_codegen_utils/codegen_backend.rs +++ b/src/librustc_codegen_utils/codegen_backend.rs @@ -7,7 +7,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] use std::any::Any; -use std::sync::mpsc; use syntax::symbol::Symbol; use rustc::session::Session; @@ -36,7 +35,6 @@ pub trait CodegenBackend { tcx: TyCtxt<'tcx>, metadata: EncodedMetadata, need_metadata_module: bool, - rx: mpsc::Receiver>, ) -> Box; /// This is called on the returned `Box` from `codegen_backend` diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 37b33466d70b8..6abc6e32d243b 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -54,7 +54,6 @@ use std::fs; use std::io::{self, Write}; use std::iter; use std::path::PathBuf; -use std::sync::mpsc; use std::cell::RefCell; use std::rc::Rc; @@ -816,7 +815,6 @@ pub fn create_global_ctxt( defs: hir::map::Definitions, resolutions: Resolutions, outputs: OutputFilenames, - tx: mpsc::Sender>, crate_name: &str, ) -> BoxedGlobalCtxt { let sess = compiler.session().clone(); @@ -858,7 +856,6 @@ pub fn create_global_ctxt( hir_map, query_result_on_disk_cache, &crate_name, - tx, &outputs ); @@ -1068,7 +1065,6 @@ fn encode_and_write_metadata( pub fn start_codegen<'tcx>( codegen_backend: &dyn CodegenBackend, tcx: TyCtxt<'tcx>, - rx: mpsc::Receiver>, outputs: &OutputFilenames, ) -> Box { if log_enabled!(::log::Level::Info) { @@ -1082,7 +1078,7 @@ pub fn start_codegen<'tcx>( tcx.sess.profiler(|p| p.start_activity("codegen crate")); let codegen = time(tcx.sess, "codegen", move || { - codegen_backend.codegen_crate(tcx, metadata, need_metadata_module, rx) + codegen_backend.codegen_crate(tcx, metadata, need_metadata_module) }); tcx.sess.profiler(|p| p.end_activity("codegen crate")); diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index ff5cd8b8c695d..cd72dc9453c7e 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -10,7 +10,6 @@ use rustc::ty::steal::Steal; use rustc::dep_graph::DepGraph; use std::cell::{Ref, RefMut, RefCell}; use std::rc::Rc; -use std::sync::mpsc; use std::any::Any; use std::mem; use syntax::{self, ast}; @@ -80,8 +79,6 @@ pub(crate) struct Queries { dep_graph: Query, lower_to_hir: Query<(Steal, ExpansionResult)>, prepare_outputs: Query, - codegen_channel: Query<(Steal>>, - Steal>>)>, global_ctxt: Query, ongoing_codegen: Query>, link: Query<()>, @@ -211,14 +208,6 @@ impl Compiler { }) } - pub fn codegen_channel(&self) -> Result<&Query<(Steal>>, - Steal>>)>> { - self.queries.codegen_channel.compute(|| { - let (tx, rx) = mpsc::channel(); - Ok((Steal::new(tx), Steal::new(rx))) - }) - } - pub fn global_ctxt(&self) -> Result<&Query> { self.queries.global_ctxt.compute(|| { let crate_name = self.crate_name()?.peek().clone(); @@ -226,21 +215,18 @@ impl Compiler { let hir = self.lower_to_hir()?; let hir = hir.peek(); let (ref hir_forest, ref expansion) = *hir; - let tx = self.codegen_channel()?.peek().0.steal(); Ok(passes::create_global_ctxt( self, hir_forest.steal(), expansion.defs.steal(), expansion.resolutions.steal(), outputs, - tx, &crate_name)) }) } pub fn ongoing_codegen(&self) -> Result<&Query>> { self.queries.ongoing_codegen.compute(|| { - let rx = self.codegen_channel()?.peek().1.steal(); let outputs = self.prepare_outputs()?; self.global_ctxt()?.peek_mut().enter(|tcx| { tcx.analysis(LOCAL_CRATE).ok(); @@ -251,7 +237,6 @@ impl Compiler { Ok(passes::start_codegen( &***self.codegen_backend(), tcx, - rx, &*outputs.peek() )) }) diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs index ec1868f32d487..c1bcb8a1aa262 100644 --- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs +++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs @@ -64,7 +64,6 @@ impl CodegenBackend for TheBackend { tcx: TyCtxt<'tcx>, _metadata: EncodedMetadata, _need_metadata_module: bool, - _rx: mpsc::Receiver> ) -> Box { use rustc::hir::def_id::LOCAL_CRATE; From bc2a373af216aa40032cf51fb435b21f416f0b26 Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 25 Sep 2019 20:38:27 +0100 Subject: [PATCH 197/413] Fix fallout --- src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr index a5c9ed3478cf4..28c837adac3a1 100644 --- a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr +++ b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr @@ -1,8 +1,8 @@ error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:11:15 + --> $DIR/ty_tykind_usage.rs:11:16 | LL | let kind = TyKind::Bool; - | ^^^^^^ help: try using ty:: directly: `ty` + | ^^^^^^ help: try using ty:: directly: `ty` | note: lint level defined here --> $DIR/ty_tykind_usage.rs:9:8 From f93827f9e446e52619953c3ad2aa6604dfc9f986 Mon Sep 17 00:00:00 2001 From: AnthonyMikh Date: Thu, 26 Sep 2019 00:31:16 +0300 Subject: [PATCH 198/413] Simplify `Emitter::fix_multispan_in_std_macros` 1. Rewrite `if let` into `match` to return earl and avoid indenting giant block 2. Assign `spans_updated` only once --- src/librustc_errors/emitter.rs | 129 +++++++++++++++++---------------- 1 file changed, 65 insertions(+), 64 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 362e28661d919..efb5c63bd0847 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -295,81 +295,82 @@ pub trait Emitter { source_map: &Option>, span: &mut MultiSpan, always_backtrace: bool) -> bool { - let mut spans_updated = false; + let sm = match source_map { + Some(ref sm) => sm, + None => return false, + }; - if let Some(ref sm) = source_map { - let mut before_after: Vec<(Span, Span)> = vec![]; - let mut new_labels: Vec<(Span, String)> = vec![]; + let mut before_after: Vec<(Span, Span)> = vec![]; + let mut new_labels: Vec<(Span, String)> = vec![]; - // First, find all the spans in <*macros> and point instead at their use site - for sp in span.primary_spans() { - if sp.is_dummy() { + // First, find all the spans in <*macros> and point instead at their use site + for sp in span.primary_spans() { + if sp.is_dummy() { + continue; + } + let call_sp = sm.call_span_if_macro(*sp); + if call_sp != *sp && !always_backtrace { + before_after.push((*sp, call_sp)); + } + let backtrace_len = sp.macro_backtrace().len(); + for (i, trace) in sp.macro_backtrace().iter().rev().enumerate() { + // Only show macro locations that are local + // and display them like a span_note + if trace.def_site_span.is_dummy() { continue; } - let call_sp = sm.call_span_if_macro(*sp); - if call_sp != *sp && !always_backtrace { - before_after.push((*sp, call_sp)); + if always_backtrace { + new_labels.push((trace.def_site_span, + format!("in this expansion of `{}`{}", + trace.macro_decl_name, + if backtrace_len > 2 { + // if backtrace_len == 1 it'll be pointed + // at by "in this macro invocation" + format!(" (#{})", i + 1) + } else { + String::new() + }))); } - let backtrace_len = sp.macro_backtrace().len(); - for (i, trace) in sp.macro_backtrace().iter().rev().enumerate() { - // Only show macro locations that are local - // and display them like a span_note - if trace.def_site_span.is_dummy() { - continue; - } - if always_backtrace { - new_labels.push((trace.def_site_span, - format!("in this expansion of `{}`{}", - trace.macro_decl_name, - if backtrace_len > 2 { - // if backtrace_len == 1 it'll be pointed - // at by "in this macro invocation" - format!(" (#{})", i + 1) - } else { - String::new() - }))); - } - // Check to make sure we're not in any <*macros> - if !sm.span_to_filename(trace.def_site_span).is_macros() && - !trace.macro_decl_name.starts_with("desugaring of ") && - !trace.macro_decl_name.starts_with("#[") || - always_backtrace { - new_labels.push((trace.call_site, - format!("in this macro invocation{}", - if backtrace_len > 2 && always_backtrace { - // only specify order when the macro - // backtrace is multiple levels deep - format!(" (#{})", i + 1) - } else { - String::new() - }))); - if !always_backtrace { - break; - } + // Check to make sure we're not in any <*macros> + if !sm.span_to_filename(trace.def_site_span).is_macros() && + !trace.macro_decl_name.starts_with("desugaring of ") && + !trace.macro_decl_name.starts_with("#[") || + always_backtrace { + new_labels.push((trace.call_site, + format!("in this macro invocation{}", + if backtrace_len > 2 && always_backtrace { + // only specify order when the macro + // backtrace is multiple levels deep + format!(" (#{})", i + 1) + } else { + String::new() + }))); + if !always_backtrace { + break; } } } - for (label_span, label_text) in new_labels { - span.push_span_label(label_span, label_text); + } + for (label_span, label_text) in new_labels { + span.push_span_label(label_span, label_text); + } + for sp_label in span.span_labels() { + if sp_label.span.is_dummy() { + continue; } - for sp_label in span.span_labels() { - if sp_label.span.is_dummy() { - continue; - } - if sm.span_to_filename(sp_label.span.clone()).is_macros() && - !always_backtrace - { - let v = sp_label.span.macro_backtrace(); - if let Some(use_site) = v.last() { - before_after.push((sp_label.span.clone(), use_site.call_site.clone())); - } + if sm.span_to_filename(sp_label.span.clone()).is_macros() && + !always_backtrace + { + let v = sp_label.span.macro_backtrace(); + if let Some(use_site) = v.last() { + before_after.push((sp_label.span.clone(), use_site.call_site.clone())); } } - // After we have them, make sure we replace these 'bad' def sites with their use sites - for (before, after) in before_after { - span.replace(before, after); - spans_updated = true; - } + } + // After we have them, make sure we replace these 'bad' def sites with their use sites + let spans_updated = !before_after.is_empty(); + for (before, after) in before_after { + span.replace(before, after); } spans_updated From ea328625039229f9ad0002a68f1a86691a065cf6 Mon Sep 17 00:00:00 2001 From: AnthonyMikh Date: Thu, 26 Sep 2019 00:38:36 +0300 Subject: [PATCH 199/413] Use `sort_by_key` rather than `sort_by` --- src/librustc_errors/emitter.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index efb5c63bd0847..7513a9203fe25 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -954,9 +954,9 @@ impl EmitterWriter { // | | | // | | something about `foo` // | something about `fn foo()` - annotations_position.sort_by(|a, b| { + annotations_position.sort_by_key(|x| { // Decreasing order. When `a` and `b` are the same length, prefer `Primary`. - (a.1.len(), !a.1.is_primary).cmp(&(b.1.len(), !b.1.is_primary)).reverse() + (Reverse(a.1.len()), a.1.is_primary) }); // Write the underlines. From 7a0725fdaf964fa1bf60eefb0cc5846b687426bf Mon Sep 17 00:00:00 2001 From: AnthonyMikh Date: Thu, 26 Sep 2019 00:42:55 +0300 Subject: [PATCH 200/413] Simplify `style_or_override` --- src/librustc_errors/emitter.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 7513a9203fe25..b8b7488d8ae45 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -1066,13 +1066,11 @@ impl EmitterWriter { let padding = " ".repeat(padding + label.len() + 5); /// Returns `true` if `style`, or the override if present and the style is `NoStyle`. - fn style_or_override(style: Style, override_style: Option