From d189e6dc2a3fd164e7c52a3fd5660ccc48355839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 14 Mar 2019 16:09:47 -0700 Subject: [PATCH 01/12] When moving out of a for loop head, suggest borrowing it When encountering code like the following, suggest borrowing the for loop head to avoid moving it into the for loop pattern: ``` fn main() { let a = vec![1, 2, 3]; for i in &a { for j in a { println!("{} * {} = {}", i, j, i * j); } } } ``` --- src/librustc/hir/lowering.rs | 3 ++- src/librustc_borrowck/borrowck/mod.rs | 14 +++++++++++ .../ui/suggestions/borrow-for-loop-head.rs | 10 ++++++++ .../suggestions/borrow-for-loop-head.stderr | 24 +++++++++++++++++++ 4 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/suggestions/borrow-for-loop-head.rs create mode 100644 src/test/ui/suggestions/borrow-for-loop-head.stderr diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 949fdd2682b96..34f792b32da54 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -4334,13 +4334,14 @@ impl<'a> LoweringContext<'a> { // } // expand - let head = self.lower_expr(head); + let mut head = self.lower_expr(head); let head_sp = head.span; let desugared_span = self.mark_span_with_reason( CompilerDesugaringKind::ForLoop, head_sp, None, ); + head.span = desugared_span; let iter = self.str_to_ident("iter"); diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index da065f9e05d9e..5b574d8caca88 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -35,6 +35,7 @@ use std::rc::Rc; use rustc_data_structures::sync::Lrc; use std::hash::{Hash, Hasher}; use syntax::ast; +use syntax::source_map::CompilerDesugaringKind; use syntax_pos::{MultiSpan, Span}; use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use log::debug; @@ -746,6 +747,19 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { }, moved_lp.ty)); } + if let (Some(CompilerDesugaringKind::ForLoop), Ok(snippet)) = ( + move_span.compiler_desugaring_kind(), + self.tcx.sess.source_map().span_to_snippet(move_span), + ) { + if !snippet.starts_with("&") { + err.span_suggestion( + move_span, + "consider borrowing this to avoid moving it into the for loop", + format!("&{}", snippet), + Applicability::MaybeIncorrect, + ); + } + } // Note: we used to suggest adding a `ref binding` or calling // `clone` but those suggestions have been removed because diff --git a/src/test/ui/suggestions/borrow-for-loop-head.rs b/src/test/ui/suggestions/borrow-for-loop-head.rs new file mode 100644 index 0000000000000..c2bda55e58903 --- /dev/null +++ b/src/test/ui/suggestions/borrow-for-loop-head.rs @@ -0,0 +1,10 @@ +fn main() { + let a = vec![1, 2, 3]; + for i in &a { + for j in a { + //~^ ERROR cannot move out of `a` because it is borrowed + //~| ERROR use of moved value: `a` + println!("{} * {} = {}", i, j, i * j); + } + } +} diff --git a/src/test/ui/suggestions/borrow-for-loop-head.stderr b/src/test/ui/suggestions/borrow-for-loop-head.stderr new file mode 100644 index 0000000000000..17ac3fe86d083 --- /dev/null +++ b/src/test/ui/suggestions/borrow-for-loop-head.stderr @@ -0,0 +1,24 @@ +error[E0505]: cannot move out of `a` because it is borrowed + --> $DIR/borrow-for-loop-head.rs:4:18 + | +LL | for i in &a { + | - borrow of `a` occurs here +LL | for j in a { + | ^ move out of `a` occurs here + +error[E0382]: use of moved value: `a` + --> $DIR/borrow-for-loop-head.rs:4:18 + | +LL | for j in a { + | ^ value moved here in previous iteration of loop + | + = note: move occurs because `a` has type `std::vec::Vec`, which does not implement the `Copy` trait +help: consider borrowing this to avoid moving it into the for loop + | +LL | for j in &a { + | ^^ + +error: aborting due to 2 previous errors + +Some errors occurred: E0382, E0505. +For more information about an error, try `rustc --explain E0382`. From fbc4326f4b249413fd71fe11a93ecf11f7533116 Mon Sep 17 00:00:00 2001 From: Kornel Date: Fri, 15 Mar 2019 15:04:34 +0000 Subject: [PATCH 02/12] Track changes to robots.txt --- src/doc/robots.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/doc/robots.txt diff --git a/src/doc/robots.txt b/src/doc/robots.txt new file mode 100644 index 0000000000000..a54ec508c1bef --- /dev/null +++ b/src/doc/robots.txt @@ -0,0 +1,19 @@ +# NB: This file is not automatically deployed. After changes, it needs to be uploaded manually to doc.rust-lang.org +User-agent: * +Disallow: /0.3/ +Disallow: /0.4/ +Disallow: /0.5/ +Disallow: /0.6/ +Disallow: /0.7/ +Disallow: /0.8/ +Disallow: /0.9/ +Disallow: /0.10/ +Disallow: /0.11.0/ +Disallow: /0.12.0/ +Disallow: /1.0.0-alpha/ +Disallow: /1.0.0-alpha.2/ +Disallow: /1.0.0-beta/ +Disallow: /1.0.0-beta.2/ +Disallow: /1.0.0-beta.3/ +Disallow: /1.0.0-beta.4/ +Disallow: /1.0.0-beta.5/ From f4742f46fe540e289888eec0bac077ff606f63c5 Mon Sep 17 00:00:00 2001 From: Tomas Koutsky Date: Fri, 15 Mar 2019 17:42:34 +0100 Subject: [PATCH 03/12] Add def getting methods to librustc/ty/context --- src/librustc/middle/dead.rs | 4 ++-- src/librustc/middle/expr_use_visitor.rs | 3 +-- src/librustc/middle/reachable.rs | 2 +- src/librustc/ty/context.rs | 9 +++++++++ src/librustc_lint/unused.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 6 ++---- src/librustc_passes/rvalue_promotion.rs | 3 +-- src/librustc_privacy/lib.rs | 6 +++--- src/librustc_save_analysis/lib.rs | 4 ++-- src/librustc_typeck/check/mod.rs | 4 ++-- 10 files changed, 24 insertions(+), 19 deletions(-) diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 94de999c25da8..c199b8273263c 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -92,8 +92,8 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } fn lookup_and_handle_method(&mut self, id: hir::HirId) { - if let Some(def) = self.tables.type_dependent_defs().get(id) { - self.check_def_id(def.def_id()); + if let Some(def_id) = self.tables.type_dependent_def_id(id) { + self.check_def_id(def_id); } else { bug!("no type-dependent def for method"); } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 8ada67efaafdd..db640b581d353 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -559,8 +559,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } ty::Error => { } _ => { - if let Some(def) = self.mc.tables.type_dependent_defs().get(call.hir_id) { - let def_id = def.def_id(); + if let Some(def_id) = self.mc.tables.type_dependent_def_id(call.hir_id) { let call_scope = region::Scope { id: call.hir_id.local_id, data: region::ScopeData::Node diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 72f6d22b696f7..9a71020d65d03 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -97,7 +97,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { Some(self.tables.qpath_def(qpath, expr.hir_id)) } hir::ExprKind::MethodCall(..) => { - self.tables.type_dependent_defs().get(expr.hir_id).cloned() + self.tables.type_dependent_def(expr.hir_id) } _ => None }; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index ecf1d8a980a8d..2fc95641693ef 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -482,6 +482,15 @@ impl<'tcx> TypeckTables<'tcx> { } } + pub fn type_dependent_def(&self, id: HirId) -> Option { + validate_hir_id_for_typeck_tables(self.local_id_root, id, false); + self.type_dependent_defs.get(&id.local_id).cloned() + } + + pub fn type_dependent_def_id(&self, id: HirId) -> Option { + self.type_dependent_def(id).map(|def| def.def_id()) + } + pub fn type_dependent_defs_mut(&mut self) -> LocalTableInContextMut<'_, Def> { LocalTableInContextMut { local_id_root: self.local_id_root, diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 86b8b276eafe5..2612efd83164c 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -112,7 +112,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { } }, hir::ExprKind::MethodCall(..) => { - cx.tables.type_dependent_defs().get(expr.hir_id).cloned() + cx.tables.type_dependent_def(expr.hir_id) }, _ => None }; diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 7749b3a5ca49e..8ca75831235f7 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -835,13 +835,11 @@ fn method_callee<'a, 'gcx, 'tcx>( let (def_id, substs, user_ty) = match overloaded_callee { Some((def_id, substs)) => (def_id, substs, None), None => { - let type_dependent_defs = cx.tables().type_dependent_defs(); - let def = type_dependent_defs - .get(expr.hir_id) + let def = cx.tables().type_dependent_def(expr.hir_id) .unwrap_or_else(|| { span_bug!(expr.span, "no type-dependent def for method callee") }); - let user_ty = user_substs_applied_to_def(cx, expr.hir_id, def); + let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def); debug!("method_callee: user_ty={:?}", user_ty); (def.def_id(), cx.tables().node_substs(expr.hir_id), user_ty) } diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 6de98675a3dc8..fcd51062cd97a 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -406,8 +406,7 @@ fn check_expr_kind<'a, 'tcx>( for index in hirvec.iter() { method_call_result &= v.check_expr(index); } - if let Some(def) = v.tables.type_dependent_defs().get(e.hir_id) { - let def_id = def.def_id(); + if let Some(def_id) = v.tables.type_dependent_def_id(e.hir_id) { match v.tcx.associated_item(def_id).container { ty::ImplContainer(_) => method_call_result & v.handle_const_fn_call(def_id), ty::TraitContainer(_) => NotPromotable, diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 52514a3ca97d6..98ee871489db8 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1041,8 +1041,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { hir::ExprKind::MethodCall(_, span, _) => { // Method calls have to be checked specially. self.span = span; - if let Some(def) = self.tables.type_dependent_defs().get(expr.hir_id) { - if self.visit(self.tcx.type_of(def.def_id())) { + if let Some(def_id) = self.tables.type_dependent_def_id(expr.hir_id) { + if self.visit(self.tcx.type_of(def_id)) { return; } } else { @@ -1071,7 +1071,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { _ => None, } hir::QPath::TypeRelative(..) => { - self.tables.type_dependent_defs().get(id).cloned() + self.tables.type_dependent_def(id) } }; if let Some(def) = def { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index d80f3e5ce759c..f6a43e888d206 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -565,8 +565,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } ast::ExprKind::MethodCall(ref seg, ..) => { let expr_hir_id = self.tcx.hir().definitions().node_to_hir_id(expr.id); - let method_id = match self.tables.type_dependent_defs().get(expr_hir_id) { - Some(id) => id.def_id(), + let method_id = match self.tables.type_dependent_def_id(expr_hir_id) { + Some(id) => id, None => { debug!("Could not resolve method id for {:?}", expr); return None; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 28c79ce0c74e8..ceb33439c3ec7 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4757,10 +4757,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { (self.to_ty(qself), qself, segment) } }; - if let Some(cached_def) = self.tables.borrow().type_dependent_defs().get(hir_id) { + if let Some(cached_def) = self.tables.borrow().type_dependent_def(hir_id) { // Return directly on cache hit. This is useful to avoid doubly reporting // errors with default match binding modes. See #44614. - return (*cached_def, Some(ty), slice::from_ref(&**item_segment)) + return (cached_def, Some(ty), slice::from_ref(&**item_segment)) } let item_name = item_segment.ident; let def = match self.resolve_ufcs(span, item_name, ty, hir_id) { From b392c5e3c17396f3987f671a61fa9fbf9f999dae Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Sat, 16 Mar 2019 13:14:01 -0400 Subject: [PATCH 04/12] use the identifier span for missing struct field --- src/librustc_typeck/check/_match.rs | 16 ++++++++-------- src/test/ui/issues/issue-17800.stderr | 4 ++-- src/test/ui/issues/issue-51102.stderr | 4 ++-- src/test/ui/issues/issue-52717.stderr | 2 +- src/test/ui/numeric/numeric-fields.stderr | 2 +- src/test/ui/structs/struct-field-cfg.stderr | 2 +- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 1a3ade7f8baf6..87e0f7d201c17 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -971,7 +971,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); self.field_ty(span, f, substs) }) .unwrap_or_else(|| { - inexistent_fields.push((span, field.ident)); + inexistent_fields.push(field.ident); no_field_errors = false; tcx.types.err }) @@ -987,15 +987,15 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); .collect::>(); if inexistent_fields.len() > 0 { let (field_names, t, plural) = if inexistent_fields.len() == 1 { - (format!("a field named `{}`", inexistent_fields[0].1), "this", "") + (format!("a field named `{}`", inexistent_fields[0]), "this", "") } else { (format!("fields named {}", inexistent_fields.iter() - .map(|(_, name)| format!("`{}`", name)) + .map(|ident| format!("`{}`", ident)) .collect::>() .join(", ")), "these", "s") }; - let spans = inexistent_fields.iter().map(|(span, _)| *span).collect::>(); + let spans = inexistent_fields.iter().map(|ident| ident.span).collect::>(); let mut err = struct_span_err!(tcx.sess, spans, E0026, @@ -1003,8 +1003,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); kind_name, tcx.item_path_str(variant.did), field_names); - if let Some((span, ident)) = inexistent_fields.last() { - err.span_label(*span, + if let Some(ident) = inexistent_fields.last() { + err.span_label(ident.span, format!("{} `{}` does not have {} field{}", kind_name, tcx.item_path_str(variant.did), @@ -1016,8 +1016,8 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); find_best_match_for_name(input, &ident.as_str(), None); if let Some(suggested_name) = suggested_name { err.span_suggestion( - *span, - "did you mean", + ident.span, + "a field with a similar name exists", suggested_name.to_string(), Applicability::MaybeIncorrect, ); diff --git a/src/test/ui/issues/issue-17800.stderr b/src/test/ui/issues/issue-17800.stderr index b4234245bfb38..6efc7f0c06e11 100644 --- a/src/test/ui/issues/issue-17800.stderr +++ b/src/test/ui/issues/issue-17800.stderr @@ -2,10 +2,10 @@ error[E0026]: variant `MyOption::MySome` does not have a field named `x` --> $DIR/issue-17800.rs:8:28 | LL | MyOption::MySome { x: 42 } => (), - | ^^^^^ + | ^ | | | variant `MyOption::MySome` does not have this field - | help: did you mean: `0` + | help: a field with a similar name exists: `0` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-51102.stderr b/src/test/ui/issues/issue-51102.stderr index 1b2948db2d6c3..4d4b977374ef9 100644 --- a/src/test/ui/issues/issue-51102.stderr +++ b/src/test/ui/issues/issue-51102.stderr @@ -2,7 +2,7 @@ error[E0026]: struct `SimpleStruct` does not have a field named `state` --> $DIR/issue-51102.rs:13:17 | LL | state: 0, - | ^^^^^^^^ struct `SimpleStruct` does not have this field + | ^^^^^ struct `SimpleStruct` does not have this field error[E0025]: field `no_state_here` bound multiple times in the pattern --> $DIR/issue-51102.rs:24:17 @@ -16,7 +16,7 @@ error[E0026]: variant `SimpleEnum::NoState` does not have a field named `state` --> $DIR/issue-51102.rs:33:17 | LL | state: 0 - | ^^^^^^^^ variant `SimpleEnum::NoState` does not have this field + | ^^^^^ variant `SimpleEnum::NoState` does not have this field error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-52717.stderr b/src/test/ui/issues/issue-52717.stderr index 408819813b075..468cdf2dcf921 100644 --- a/src/test/ui/issues/issue-52717.stderr +++ b/src/test/ui/issues/issue-52717.stderr @@ -5,7 +5,7 @@ LL | A::A { fob } => { println!("{}", fob); } | ^^^ | | | variant `A::A` does not have this field - | help: did you mean: `foo` + | help: a field with a similar name exists: `foo` error: aborting due to previous error diff --git a/src/test/ui/numeric/numeric-fields.stderr b/src/test/ui/numeric/numeric-fields.stderr index 1a2ad4a0c0945..ce51bbaa114fd 100644 --- a/src/test/ui/numeric/numeric-fields.stderr +++ b/src/test/ui/numeric/numeric-fields.stderr @@ -10,7 +10,7 @@ error[E0026]: struct `S` does not have a field named `0x1` --> $DIR/numeric-fields.rs:7:17 | LL | S{0: a, 0x1: b, ..} => {} - | ^^^^^^ struct `S` does not have this field + | ^^^ struct `S` does not have this field error: aborting due to 2 previous errors diff --git a/src/test/ui/structs/struct-field-cfg.stderr b/src/test/ui/structs/struct-field-cfg.stderr index c8c624d548b67..565866a682ada 100644 --- a/src/test/ui/structs/struct-field-cfg.stderr +++ b/src/test/ui/structs/struct-field-cfg.stderr @@ -22,7 +22,7 @@ error[E0026]: struct `Foo` does not have a field named `absent` --> $DIR/struct-field-cfg.rs:16:42 | LL | let Foo { present: (), #[cfg(all())] absent: () } = foo; - | ^^^^^^^^^^ struct `Foo` does not have this field + | ^^^^^^ struct `Foo` does not have this field error: aborting due to 4 previous errors From 32bcff143ebebaf9979162d0b7973194e4989ce1 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 12 Mar 2019 10:58:30 -0700 Subject: [PATCH 05/12] SGX target: fix std unit tests --- src/libstd/Cargo.toml | 4 ++ src/libstd/env.rs | 3 +- src/libstd/fs.rs | 2 +- src/libstd/net/addr.rs | 6 +++ src/libstd/net/tcp.rs | 62 +++++++++++++++++------ src/libstd/net/test.rs | 10 ++-- src/libstd/net/udp.rs | 2 +- src/libstd/path.rs | 4 +- src/libstd/process.rs | 2 +- src/libstd/sync/condvar.rs | 4 ++ src/libstd/sync/mpsc/mod.rs | 23 ++++++--- src/libstd/sys/sgx/abi/mod.rs | 5 ++ src/libstd/sys/sgx/abi/panic.rs | 2 +- src/libstd/sys/sgx/abi/tls.rs | 39 ++------------ src/libstd/sys/sgx/abi/usercalls/alloc.rs | 9 +++- src/libstd/sys/sgx/alloc.rs | 2 + src/libstd/sys/sgx/args.rs | 3 ++ src/libstd/sys/sgx/condvar.rs | 3 +- src/libstd/sys/sgx/net.rs | 60 +++++++++++++++++++--- src/libstd/sys/sgx/os.rs | 4 ++ src/libstd/sys/sgx/rwlock.rs | 51 ++++++++++++++----- src/libstd/sys/sgx/stack_overflow.rs | 1 + src/libstd/sys/sgx/thread.rs | 5 ++ src/libstd/sys/sgx/waitqueue.rs | 12 ++++- src/libstd/thread/local.rs | 6 +-- src/libstd/thread/mod.rs | 5 +- src/tools/tidy/src/pal.rs | 1 + 27 files changed, 236 insertions(+), 94 deletions(-) diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 1a6b58f35b398..b2eaf956d0e2d 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -72,3 +72,7 @@ wasm-bindgen-threads = [] # https://github.com/rust-lang-nursery/stdsimd/blob/master/crates/std_detect/Cargo.toml std_detect_file_io = [] std_detect_dlsym_getauxval = [] + +[package.metadata.fortanix-sgx] +# Maximum possible number of threads when testing +threads = 125 diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 97c67f562a7df..f723a2b0bb281 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -975,7 +975,7 @@ mod tests { use crate::path::Path; #[test] - #[cfg_attr(target_os = "emscripten", ignore)] + #[cfg_attr(any(target_os = "emscripten", target_env = "sgx"), ignore)] fn test_self_exe_path() { let path = current_exe(); assert!(path.is_ok()); @@ -989,6 +989,7 @@ mod tests { fn test() { assert!((!Path::new("test-path").is_absolute())); + #[cfg(not(target_env = "sgx"))] current_dir().unwrap(); } diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 8c3d0da0a7e40..dfff44b88ea78 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -2095,7 +2095,7 @@ impl AsInnerMut for DirBuilder { } } -#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))] +#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))] mod tests { use crate::io::prelude::*; diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index f5a87cc3ea67a..eaa6a070154f7 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -941,7 +941,10 @@ mod tests { assert_eq!(Ok(vec![a]), tsa(("2a02:6b8:0:1::1", 53))); let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924); + #[cfg(not(target_env = "sgx"))] assert!(tsa(("localhost", 23924)).unwrap().contains(&a)); + #[cfg(target_env = "sgx")] + let _ = a; } #[test] @@ -953,7 +956,10 @@ mod tests { assert_eq!(Ok(vec![a]), tsa("[2a02:6b8:0:1::1]:53")); let a = sa4(Ipv4Addr::new(127, 0, 0, 1), 23924); + #[cfg(not(target_env = "sgx"))] assert!(tsa("localhost:23924").unwrap().contains(&a)); + #[cfg(target_env = "sgx")] + let _ = a; } #[test] diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs index ce0c5c0bb0dc7..304cdb0155814 100644 --- a/src/libstd/net/tcp.rs +++ b/src/libstd/net/tcp.rs @@ -929,12 +929,12 @@ impl fmt::Debug for TcpListener { #[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))] mod tests { + use crate::fmt; use crate::io::{ErrorKind, IoVec, IoVecMut}; use crate::io::prelude::*; use crate::net::*; use crate::net::test::{next_test_ip4, next_test_ip6}; use crate::sync::mpsc::channel; - use crate::sys_common::AsInner; use crate::time::{Instant, Duration}; use crate::thread; @@ -1129,7 +1129,7 @@ mod tests { connect(i + 1, addr); t!(stream.write(&[i as u8])); }); - t.join().ok().unwrap(); + t.join().ok().expect("thread panicked"); } } @@ -1162,7 +1162,7 @@ mod tests { connect(i + 1, addr); t!(stream.write(&[99])); }); - t.join().ok().unwrap(); + t.join().ok().expect("thread panicked"); } } @@ -1377,6 +1377,8 @@ mod tests { } #[test] + // FIXME: https://github.com/fortanix/rust-sgx/issues/110 + #[cfg_attr(target_env = "sgx", ignore)] fn shutdown_smoke() { each_ip(&mut |addr| { let a = t!(TcpListener::bind(&addr)); @@ -1397,6 +1399,8 @@ mod tests { } #[test] + // FIXME: https://github.com/fortanix/rust-sgx/issues/110 + #[cfg_attr(target_env = "sgx", ignore)] fn close_readwrite_smoke() { each_ip(&mut |addr| { let a = t!(TcpListener::bind(&addr)); @@ -1550,30 +1554,51 @@ mod tests { #[test] fn debug() { - let name = if cfg!(windows) {"socket"} else {"fd"}; + #[cfg(not(target_env = "sgx"))] + fn render_socket_addr<'a>(addr: &'a SocketAddr) -> impl fmt::Debug + 'a { + addr + } + #[cfg(target_env = "sgx")] + fn render_socket_addr<'a>(addr: &'a SocketAddr) -> impl fmt::Debug + 'a { + addr.to_string() + } + + #[cfg(unix)] + use crate::os::unix::io::AsRawFd; + #[cfg(target_env = "sgx")] + use crate::os::fortanix_sgx::io::AsRawFd; + #[cfg(not(windows))] + fn render_inner(addr: &dyn AsRawFd) -> impl fmt::Debug { + addr.as_raw_fd() + } + #[cfg(windows)] + fn render_inner(addr: &dyn os::windows::io::AsRawSocket) -> impl fmt::Debug { + addr.as_raw_socket() + } + + let inner_name = if cfg!(windows) {"socket"} else {"fd"}; let socket_addr = next_test_ip4(); let listener = t!(TcpListener::bind(&socket_addr)); - let listener_inner = listener.0.socket().as_inner(); let compare = format!("TcpListener {{ addr: {:?}, {}: {:?} }}", - socket_addr, name, listener_inner); + render_socket_addr(&socket_addr), + inner_name, + render_inner(&listener)); assert_eq!(format!("{:?}", listener), compare); - let stream = t!(TcpStream::connect(&("localhost", - socket_addr.port()))); - let stream_inner = stream.0.socket().as_inner(); - let compare = format!("TcpStream {{ addr: {:?}, \ - peer: {:?}, {}: {:?} }}", - stream.local_addr().unwrap(), - stream.peer_addr().unwrap(), - name, - stream_inner); + let stream = t!(TcpStream::connect(&("localhost", socket_addr.port()))); + let compare = format!("TcpStream {{ addr: {:?}, peer: {:?}, {}: {:?} }}", + render_socket_addr(&stream.local_addr().unwrap()), + render_socket_addr(&stream.peer_addr().unwrap()), + inner_name, + render_inner(&stream)); assert_eq!(format!("{:?}", stream), compare); } // FIXME: re-enabled bitrig/openbsd tests once their socket timeout code // no longer has rounding errors. #[cfg_attr(any(target_os = "bitrig", target_os = "netbsd", target_os = "openbsd"), ignore)] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 #[test] fn timeouts() { let addr = next_test_ip4(); @@ -1601,6 +1626,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn test_read_timeout() { let addr = next_test_ip4(); let listener = t!(TcpListener::bind(&addr)); @@ -1618,6 +1644,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn test_read_with_timeout() { let addr = next_test_ip4(); let listener = t!(TcpListener::bind(&addr)); @@ -1661,6 +1688,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] fn nodelay() { let addr = next_test_ip4(); let _listener = t!(TcpListener::bind(&addr)); @@ -1675,6 +1703,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] fn ttl() { let ttl = 100; @@ -1691,6 +1720,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] fn set_nonblocking() { let addr = next_test_ip4(); let listener = t!(TcpListener::bind(&addr)); @@ -1712,6 +1742,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn peek() { each_ip(&mut |addr| { let (txdone, rxdone) = channel(); @@ -1743,6 +1774,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn connect_timeout_valid() { let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let addr = listener.local_addr().unwrap(); diff --git a/src/libstd/net/test.rs b/src/libstd/net/test.rs index 89fefd9d1d5e0..e2991cbdd8822 100644 --- a/src/libstd/net/test.rs +++ b/src/libstd/net/test.rs @@ -36,12 +36,16 @@ pub fn tsa(a: A) -> Result, String> { // all want to use ports. This function figures out which workspace // it is running in and assigns a port range based on it. fn base_port() -> u16 { - let cwd = env::current_dir().unwrap(); + let cwd = if cfg!(target_env = "sgx") { + String::from("sgx") + } else { + env::current_dir().unwrap().into_os_string().into_string().unwrap() + }; let dirs = ["32-opt", "32-nopt", "musl-64-opt", "cross-opt", "64-opt", "64-nopt", "64-opt-vg", "64-debug-opt", - "all-opt", "snap3", "dist"]; + "all-opt", "snap3", "dist", "sgx"]; dirs.iter().enumerate().find(|&(_, dir)| { - cwd.to_str().unwrap().contains(dir) + cwd.contains(dir) }).map(|p| p.0).unwrap_or(0) as u16 * 1000 + 19600 } diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index edc9d665444a0..951f385fb3ea5 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -806,7 +806,7 @@ impl fmt::Debug for UdpSocket { } } -#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))] +#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))] mod tests { use crate::io::ErrorKind; use crate::net::*; diff --git a/src/libstd/path.rs b/src/libstd/path.rs index ea3fcd8ce2859..4048bc4da2557 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -3801,7 +3801,7 @@ mod tests { }); ); - if cfg!(unix) { + if cfg!(unix) || cfg!(all(target_env = "sgx", target_vendor = "fortanix")) { tp!("", "foo", "foo"); tp!("foo", "bar", "foo/bar"); tp!("foo/", "bar", "foo/bar"); @@ -3960,7 +3960,7 @@ mod tests { tfn!("foo", "bar", "bar"); tfn!("foo", "", ""); tfn!("", "foo", "foo"); - if cfg!(unix) { + if cfg!(unix) || cfg!(all(target_env = "sgx", target_vendor = "fortanix")) { tfn!(".", "foo", "./foo"); tfn!("foo/", "bar", "bar"); tfn!("foo/.", "bar", "bar"); diff --git a/src/libstd/process.rs b/src/libstd/process.rs index ad86acbb47de4..054b398b01f26 100644 --- a/src/libstd/process.rs +++ b/src/libstd/process.rs @@ -1621,7 +1621,7 @@ impl Termination for ExitCode { } } -#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))] +#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))] mod tests { use crate::io::prelude::*; diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index c383f21dcd752..2e8182671dd6f 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -705,6 +705,7 @@ mod tests { #[test] #[cfg_attr(target_os = "emscripten", ignore)] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn wait_timeout_wait() { let m = Arc::new(Mutex::new(())); let c = Arc::new(Condvar::new()); @@ -724,6 +725,7 @@ mod tests { #[test] #[cfg_attr(target_os = "emscripten", ignore)] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn wait_timeout_until_wait() { let m = Arc::new(Mutex::new(())); let c = Arc::new(Condvar::new()); @@ -748,6 +750,7 @@ mod tests { #[test] #[cfg_attr(target_os = "emscripten", ignore)] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn wait_timeout_until_wake() { let pair = Arc::new((Mutex::new(false), Condvar::new())); let pair_copy = pair.clone(); @@ -771,6 +774,7 @@ mod tests { #[test] #[cfg_attr(target_os = "emscripten", ignore)] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn wait_timeout_wake() { let m = Arc::new(Mutex::new(())); let c = Arc::new(Condvar::new()); diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 90c5c50c23b9c..4ed2bfb175a46 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -1951,7 +1951,7 @@ mod tests { for _ in 0..10000 { assert_eq!(rx.recv().unwrap(), 1); } - t.join().ok().unwrap(); + t.join().ok().expect("thread panicked"); } #[test] @@ -1977,7 +1977,7 @@ mod tests { }); } drop(tx); - t.join().ok().unwrap(); + t.join().ok().expect("thread panicked"); } #[test] @@ -1996,8 +1996,8 @@ mod tests { tx2.send(1).unwrap(); } }); - t1.join().ok().unwrap(); - t2.join().ok().unwrap(); + t1.join().ok().expect("thread panicked"); + t2.join().ok().expect("thread panicked"); } #[test] @@ -2011,7 +2011,7 @@ mod tests { for _ in 0..40 { tx.send(1).unwrap(); } - t.join().ok().unwrap(); + t.join().ok().expect("thread panicked"); } #[test] @@ -2026,8 +2026,8 @@ mod tests { tx1.send(1).unwrap(); assert_eq!(rx2.recv().unwrap(), 2); }); - t1.join().ok().unwrap(); - t2.join().ok().unwrap(); + t1.join().ok().expect("thread panicked"); + t2.join().ok().expect("thread panicked"); } #[test] @@ -2225,6 +2225,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn oneshot_single_thread_recv_timeout() { let (tx, rx) = channel(); tx.send(()).unwrap(); @@ -2235,6 +2236,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn stress_recv_timeout_two_threads() { let (tx, rx) = channel(); let stress = stress_factor() + 100; @@ -2265,6 +2267,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn recv_timeout_upgrade() { let (tx, rx) = channel::<()>(); let timeout = Duration::from_millis(1); @@ -2276,6 +2279,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn stress_recv_timeout_shared() { let (tx, rx) = channel(); let stress = stress_factor() + 100; @@ -2306,6 +2310,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn very_long_recv_timeout_wont_panic() { let (tx, rx) = channel::<()>(); let join_handle = thread::spawn(move || { @@ -2325,6 +2330,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn shared_recv_timeout() { let (tx, rx) = channel(); let total = 5; @@ -2550,6 +2556,7 @@ mod sync_tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn recv_timeout() { let (tx, rx) = sync_channel::(1); assert_eq!(rx.recv_timeout(Duration::from_millis(1)), Err(RecvTimeoutError::Timeout)); @@ -2639,6 +2646,7 @@ mod sync_tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn stress_recv_timeout_two_threads() { let (tx, rx) = sync_channel::(0); @@ -2662,6 +2670,7 @@ mod sync_tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn stress_recv_timeout_shared() { const AMT: u32 = 1000; const NTHREADS: u32 = 8; diff --git a/src/libstd/sys/sgx/abi/mod.rs b/src/libstd/sys/sgx/abi/mod.rs index 7426f7be9e961..85ec8be4aae69 100644 --- a/src/libstd/sys/sgx/abi/mod.rs +++ b/src/libstd/sys/sgx/abi/mod.rs @@ -1,3 +1,5 @@ +#![cfg_attr(test, allow(unused))] // RT initialization logic is not compiled for test + use core::sync::atomic::{AtomicUsize, Ordering}; use crate::io::Write; @@ -12,8 +14,10 @@ pub mod tls; #[macro_use] pub mod usercalls; +#[cfg(not(test))] global_asm!(include_str!("entry.S")); +#[cfg(not(test))] #[no_mangle] unsafe extern "C" fn tcs_init(secondary: bool) { // Be very careful when changing this code: it runs before the binary has been @@ -48,6 +52,7 @@ unsafe extern "C" fn tcs_init(secondary: bool) { // FIXME: this item should only exist if this is linked into an executable // (main function exists). If this is a library, the crate author should be // able to specify this +#[cfg(not(test))] #[no_mangle] extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64) -> (u64, u64) { // FIXME: how to support TLS in library mode? diff --git a/src/libstd/sys/sgx/abi/panic.rs b/src/libstd/sys/sgx/abi/panic.rs index 83411cb5b4c26..de86394b4b88c 100644 --- a/src/libstd/sys/sgx/abi/panic.rs +++ b/src/libstd/sys/sgx/abi/panic.rs @@ -49,7 +49,7 @@ impl Write for SgxPanicOutput { } } -#[no_mangle] +#[cfg_attr(not(test), no_mangle)] pub extern "C" fn panic_msg(msg: &str) -> ! { let _ = SgxPanicOutput::new().map(|mut out| out.write(msg.as_bytes())); usercalls::exit(true) diff --git a/src/libstd/sys/sgx/abi/tls.rs b/src/libstd/sys/sgx/abi/tls.rs index b2a812c7231da..6b9ab7e383c01 100644 --- a/src/libstd/sys/sgx/abi/tls.rs +++ b/src/libstd/sys/sgx/abi/tls.rs @@ -10,45 +10,16 @@ const USIZE_BITS: usize = 64; const TLS_KEYS: usize = 128; // Same as POSIX minimum const TLS_KEYS_BITSET_SIZE: usize = (TLS_KEYS + (USIZE_BITS - 1)) / USIZE_BITS; +#[cfg_attr(test, linkage = "available_externally")] +#[export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_KEY_IN_USEE"] static TLS_KEY_IN_USE: SyncBitset = SYNC_BITSET_INIT; macro_rules! dup { ((* $($exp:tt)*) $($val:tt)*) => (dup!( ($($exp)*) $($val)* $($val)* )); (() $($val:tt)*) => ([$($val),*]) } -static TLS_DESTRUCTOR: [AtomicUsize; TLS_KEYS] = [ - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), - AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), AtomicUsize::new(0), -]; +#[cfg_attr(test, linkage = "available_externally")] +#[export_name = "_ZN16__rust_internals3std3sys3sgx3abi3tls14TLS_DESTRUCTORE"] +static TLS_DESTRUCTOR: [AtomicUsize; TLS_KEYS] = dup!((* * * * * * *) (AtomicUsize::new(0))); extern "C" { fn get_tls_ptr() -> *const u8; diff --git a/src/libstd/sys/sgx/abi/usercalls/alloc.rs b/src/libstd/sys/sgx/abi/usercalls/alloc.rs index b787bd1a5abac..449a5fe5ae308 100644 --- a/src/libstd/sys/sgx/abi/usercalls/alloc.rs +++ b/src/libstd/sys/sgx/abi/usercalls/alloc.rs @@ -188,8 +188,13 @@ impl User where T: UserSafe { // from outside as obtained by `super::alloc`. fn new_uninit_bytes(size: usize) -> Self { unsafe { - let ptr = super::alloc(size, T::align_of()).expect("User memory allocation failed"); - User(NonNull::new_userref(T::from_raw_sized(ptr as _, size))) + // Mustn't call alloc with size 0. + let ptr = if size > 0 { + super::alloc(size, T::align_of()).expect("User memory allocation failed") as _ + } else { + T::align_of() as _ // dangling pointer ok for size 0 + }; + User(NonNull::new_userref(T::from_raw_sized(ptr, size))) } } diff --git a/src/libstd/sys/sgx/alloc.rs b/src/libstd/sys/sgx/alloc.rs index 94dc8ec25b587..98eb8397436bf 100644 --- a/src/libstd/sys/sgx/alloc.rs +++ b/src/libstd/sys/sgx/alloc.rs @@ -4,6 +4,8 @@ use super::waitqueue::SpinMutex; // Using a SpinMutex because we never want to exit the enclave waiting for the // allocator. +#[cfg_attr(test, linkage = "available_externally")] +#[export_name = "_ZN16__rust_internals3std3sys3sgx5alloc8DLMALLOCE"] static DLMALLOC: SpinMutex = SpinMutex::new(dlmalloc::DLMALLOC_INIT); #[stable(feature = "alloc_system_type", since = "1.28.0")] diff --git a/src/libstd/sys/sgx/args.rs b/src/libstd/sys/sgx/args.rs index b73bf9213b772..a84ab4138761e 100644 --- a/src/libstd/sys/sgx/args.rs +++ b/src/libstd/sys/sgx/args.rs @@ -5,9 +5,12 @@ use crate::sys::os_str::Buf; use crate::sys_common::FromInner; use crate::slice; +#[cfg_attr(test, linkage = "available_externally")] +#[export_name = "_ZN16__rust_internals3std3sys3sgx4args4ARGSE"] static ARGS: AtomicUsize = AtomicUsize::new(0); type ArgsStore = Vec; +#[cfg_attr(test, allow(dead_code))] pub unsafe fn init(argc: isize, argv: *const *const u8) { if argc != 0 { let args = alloc::User::<[ByteBuffer]>::from_raw_parts(argv as _, argc as _); diff --git a/src/libstd/sys/sgx/condvar.rs b/src/libstd/sys/sgx/condvar.rs index e9a7684f74d00..f9a76f0baf51a 100644 --- a/src/libstd/sys/sgx/condvar.rs +++ b/src/libstd/sys/sgx/condvar.rs @@ -32,7 +32,8 @@ impl Condvar { mutex.lock() } - pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool { + pub unsafe fn wait_timeout(&self, mutex: &Mutex, _dur: Duration) -> bool { + mutex.unlock(); // don't hold the lock while panicking panic!("timeout not supported in SGX"); } diff --git a/src/libstd/sys/sgx/net.rs b/src/libstd/sys/sgx/net.rs index e167e917957f3..592b300ac667c 100644 --- a/src/libstd/sys/sgx/net.rs +++ b/src/libstd/sys/sgx/net.rs @@ -41,12 +41,29 @@ impl FromInner for Socket { } } -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct TcpStream { inner: Socket, peer_addr: Option, } +impl fmt::Debug for TcpStream { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut res = f.debug_struct("TcpStream"); + + if let Some(ref addr) = self.inner.local_addr { + res.field("addr", addr); + } + + if let Some(ref peer) = self.peer_addr { + res.field("peer", peer); + } + + res.field("fd", &self.inner.inner.as_inner()) + .finish() + } +} + fn io_err_to_addr(result: io::Result<&SocketAddr>) -> io::Result { match result { Ok(saddr) => Ok(saddr.to_string()), @@ -75,16 +92,32 @@ impl TcpStream { Ok(TcpStream { inner: Socket::new(fd, local_addr), peer_addr: Some(peer_addr) }) } - pub fn connect_timeout(addr: &SocketAddr, _: Duration) -> io::Result { + pub fn connect_timeout(addr: &SocketAddr, dur: Duration) -> io::Result { + if dur == Duration::default() { + return Err(io::Error::new(io::ErrorKind::InvalidInput, + "cannot set a 0 duration timeout")); + } Self::connect(Ok(addr)) // FIXME: ignoring timeout } - pub fn set_read_timeout(&self, _: Option) -> io::Result<()> { - sgx_ineffective(()) + pub fn set_read_timeout(&self, dur: Option) -> io::Result<()> { + match dur { + Some(dur) if dur == Duration::default() => { + return Err(io::Error::new(io::ErrorKind::InvalidInput, + "cannot set a 0 duration timeout")); + } + _ => sgx_ineffective(()) + } } - pub fn set_write_timeout(&self, _: Option) -> io::Result<()> { - sgx_ineffective(()) + pub fn set_write_timeout(&self, dur: Option) -> io::Result<()> { + match dur { + Some(dur) if dur == Duration::default() => { + return Err(io::Error::new(io::ErrorKind::InvalidInput, + "cannot set a 0 duration timeout")); + } + _ => sgx_ineffective(()) + } } pub fn read_timeout(&self) -> io::Result> { @@ -174,11 +207,24 @@ impl FromInner<(Socket, Option)> for TcpStream { } } -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct TcpListener { inner: Socket, } +impl fmt::Debug for TcpListener { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut res = f.debug_struct("TcpListener"); + + if let Some(ref addr) = self.inner.local_addr { + res.field("addr", addr); + } + + res.field("fd", &self.inner.inner.as_inner()) + .finish() + } +} + impl TcpListener { pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result { let addr = io_err_to_addr(addr)?; diff --git a/src/libstd/sys/sgx/os.rs b/src/libstd/sys/sgx/os.rs index 2725e66ce5de4..0bb7b897058db 100644 --- a/src/libstd/sys/sgx/os.rs +++ b/src/libstd/sys/sgx/os.rs @@ -73,7 +73,11 @@ pub fn current_exe() -> io::Result { unsupported() } +#[cfg_attr(test, linkage = "available_externally")] +#[export_name = "_ZN16__rust_internals3std3sys3sgx2os3ENVE"] static ENV: AtomicUsize = AtomicUsize::new(0); +#[cfg_attr(test, linkage = "available_externally")] +#[export_name = "_ZN16__rust_internals3std3sys3sgx2os8ENV_INITE"] static ENV_INIT: Once = Once::new(); type EnvStore = Mutex>; diff --git a/src/libstd/sys/sgx/rwlock.rs b/src/libstd/sys/sgx/rwlock.rs index 372760bbf26b4..7b113267865b6 100644 --- a/src/libstd/sys/sgx/rwlock.rs +++ b/src/libstd/sys/sgx/rwlock.rs @@ -1,6 +1,9 @@ +#[cfg(not(test))] use crate::alloc::{self, Layout}; use crate::num::NonZeroUsize; +#[cfg(not(test))] use crate::slice; +#[cfg(not(test))] use crate::str; use super::waitqueue::{ @@ -147,6 +150,7 @@ impl RWLock { // only used by __rust_rwlock_unlock below #[inline] + #[cfg_attr(test, allow(dead_code))] unsafe fn unlock(&self) { let rguard = self.readers.lock(); let wguard = self.writer.lock(); @@ -161,9 +165,11 @@ impl RWLock { pub unsafe fn destroy(&self) {} } +#[cfg(not(test))] const EINVAL: i32 = 22; // used by libunwind port +#[cfg(not(test))] #[no_mangle] pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 { if p.is_null() { @@ -173,6 +179,7 @@ pub unsafe extern "C" fn __rust_rwlock_rdlock(p: *mut RWLock) -> i32 { return 0; } +#[cfg(not(test))] #[no_mangle] pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RWLock) -> i32 { if p.is_null() { @@ -181,6 +188,7 @@ pub unsafe extern "C" fn __rust_rwlock_wrlock(p: *mut RWLock) -> i32 { (*p).write(); return 0; } +#[cfg(not(test))] #[no_mangle] pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 { if p.is_null() { @@ -192,6 +200,7 @@ pub unsafe extern "C" fn __rust_rwlock_unlock(p: *mut RWLock) -> i32 { // the following functions are also used by the libunwind port. They're // included here to make sure parallel codegen and LTO don't mess things up. +#[cfg(not(test))] #[no_mangle] pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) { if s < 0 { @@ -203,17 +212,20 @@ pub unsafe extern "C" fn __rust_print_err(m: *mut u8, s: i32) { } } +#[cfg(not(test))] #[no_mangle] // NB. used by both libunwind and libpanic_abort pub unsafe extern "C" fn __rust_abort() { crate::sys::abort_internal(); } +#[cfg(not(test))] #[no_mangle] pub unsafe extern "C" fn __rust_c_alloc(size: usize, align: usize) -> *mut u8 { alloc::alloc(Layout::from_size_align_unchecked(size, align)) } +#[cfg(not(test))] #[no_mangle] pub unsafe extern "C" fn __rust_c_dealloc(ptr: *mut u8, size: usize, align: usize) { alloc::dealloc(ptr, Layout::from_size_align_unchecked(size, align)) @@ -221,15 +233,13 @@ pub unsafe extern "C" fn __rust_c_dealloc(ptr: *mut u8, size: usize, align: usiz #[cfg(test)] mod tests { - use super::*; use core::array::FixedSizeArray; - use crate::mem::MaybeUninit; - use crate::{mem, ptr}; + use crate::mem::{self, MaybeUninit}; - // The below test verifies that the bytes of initialized RWLock are the ones - // we use in libunwind. - // If they change we need to update src/UnwindRustSgx.h in libunwind. + // Verify that the bytes of initialized RWLock are the same as in + // libunwind. If they change, `src/UnwindRustSgx.h` in libunwind needs to + // be changed too. #[test] fn test_c_rwlock_initializer() { const RWLOCK_INIT: &[u8] = &[ @@ -251,11 +261,28 @@ mod tests { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ]; - let mut init = MaybeUninit::::zeroed(); - init.set(RWLock::new()); - assert_eq!( - mem::transmute::<_, [u8; 128]>(init.into_inner()).as_slice(), - RWLOCK_INIT - ); + #[inline(never)] + fn zero_stack() { + test::black_box(MaybeUninit::<[RWLock; 16]>::zeroed()); + } + + #[inline(never)] + unsafe fn rwlock_new(init: &mut MaybeUninit) { + init.set(RWLock::new()); + } + + unsafe { + // try hard to make sure that the padding/unused bytes in RWLock + // get initialized as 0. If the assertion below fails, that might + // just be an issue with the test code and not with the value of + // RWLOCK_INIT. + zero_stack(); + let mut init = MaybeUninit::::zeroed(); + rwlock_new(&mut init); + assert_eq!( + mem::transmute::<_, [u8; 128]>(init.into_initialized()).as_slice(), + RWLOCK_INIT + ) + }; } } diff --git a/src/libstd/sys/sgx/stack_overflow.rs b/src/libstd/sys/sgx/stack_overflow.rs index c0e7c824615c8..e63fa2bed65d5 100644 --- a/src/libstd/sys/sgx/stack_overflow.rs +++ b/src/libstd/sys/sgx/stack_overflow.rs @@ -6,6 +6,7 @@ impl Handler { } } +#[cfg_attr(test, allow(dead_code))] pub unsafe fn init() { } diff --git a/src/libstd/sys/sgx/thread.rs b/src/libstd/sys/sgx/thread.rs index 13569062ac184..a3637723ba1bd 100644 --- a/src/libstd/sys/sgx/thread.rs +++ b/src/libstd/sys/sgx/thread.rs @@ -1,3 +1,4 @@ +#![cfg_attr(test, allow(dead_code))] // why is this necessary? use crate::boxed::FnBox; use crate::ffi::CStr; use crate::io; @@ -33,7 +34,11 @@ mod task_queue { } } + #[cfg_attr(test, linkage = "available_externally")] + #[export_name = "_ZN16__rust_internals3std3sys3sgx6thread15TASK_QUEUE_INITE"] static TASK_QUEUE_INIT: Once = Once::new(); + #[cfg_attr(test, linkage = "available_externally")] + #[export_name = "_ZN16__rust_internals3std3sys3sgx6thread10TASK_QUEUEE"] static mut TASK_QUEUE: Option>> = None; pub(super) fn lock() -> MutexGuard<'static, Vec> { diff --git a/src/libstd/sys/sgx/waitqueue.rs b/src/libstd/sys/sgx/waitqueue.rs index 1dbf2afbf4987..3f5e03ddad69e 100644 --- a/src/libstd/sys/sgx/waitqueue.rs +++ b/src/libstd/sys/sgx/waitqueue.rs @@ -498,6 +498,7 @@ mod spin_mutex { use super::*; use crate::sync::Arc; use crate::thread; + use crate::time::{SystemTime, Duration}; #[test] fn sleep() { @@ -507,7 +508,13 @@ mod spin_mutex { let t1 = thread::spawn(move || { *mutex2.lock() = 1; }); - thread::sleep_ms(50); + + // "sleep" for 50ms + // FIXME: https://github.com/fortanix/rust-sgx/issues/31 + let start = SystemTime::now(); + let max = Duration::from_millis(50); + while start.elapsed().unwrap() < max {} + assert_eq!(*guard, 0); drop(guard); t1.join().unwrap(); @@ -530,7 +537,8 @@ mod tests { let locked = wq.lock(); let t1 = thread::spawn(move || { - assert!(WaitQueue::notify_one(wq2.lock()).is_none()) + // if we obtain the lock, the main thread should be waiting + assert!(WaitQueue::notify_one(wq2.lock()).is_ok()); }); WaitQueue::wait(locked); diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 7ad6b124e3a38..b73c5856b8805 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -530,7 +530,7 @@ mod tests { thread::spawn(|| { assert!(FOO.try_with(|_| ()).is_ok()); - }).join().ok().unwrap(); + }).join().ok().expect("thread panicked"); } #[test] @@ -584,7 +584,7 @@ mod tests { thread::spawn(move|| { drop(S1); - }).join().ok().unwrap(); + }).join().ok().expect("thread panicked"); } #[test] @@ -600,7 +600,7 @@ mod tests { thread::spawn(move|| unsafe { K1.with(|s| *s.get() = Some(S1)); - }).join().ok().unwrap(); + }).join().ok().expect("thread panicked"); } // Note that this test will deadlock if TLS destructors aren't run (this diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 08f0aa2f0d206..8f323b59bf8e1 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -1497,7 +1497,7 @@ mod tests { fn test_unnamed_thread() { thread::spawn(move|| { assert!(thread::current().name().is_none()); - }).join().ok().unwrap(); + }).join().ok().expect("thread panicked"); } #[test] @@ -1691,6 +1691,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn test_park_timeout_unpark_not_called() { for _ in 0..10 { thread::park_timeout(Duration::from_millis(10)); @@ -1698,6 +1699,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn test_park_timeout_unpark_called_other_thread() { for _ in 0..10 { let th = thread::current(); @@ -1712,6 +1714,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn sleep_ms_smoke() { thread::sleep(Duration::from_millis(2)); } diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index ed2218f09d26b..0be3ec839e9a2 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -54,6 +54,7 @@ const EXCEPTION_PATHS: &[&str] = &[ "src/libstd/f64.rs", // Integration test for platform-specific run-time feature detection: "src/libstd/tests/run-time-detect.rs" , + "src/libstd/net/test.rs", "src/libstd/sys_common/mod.rs", "src/libstd/sys_common/net.rs", "src/libterm", // Not sure how to make this crate portable, but test crate needs it. From 64303189f0b3a111c3b1e59d77cdaad91ca90efe Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 17 Mar 2019 10:36:10 +0000 Subject: [PATCH 06/12] Use a valid name for graphviz graphs --- src/librustc_driver/pretty.rs | 12 +++++++++- src/librustc_mir/borrow_check/mod.rs | 8 +++---- src/librustc_mir/dataflow/graphviz.rs | 17 +++++++------- src/librustc_mir/dataflow/mod.rs | 12 +++++----- src/librustc_mir/transform/elaborate_drops.rs | 12 +++++----- src/librustc_mir/transform/generator.rs | 6 ++--- src/librustc_mir/transform/rustc_peek.rs | 19 ++++++++------- src/librustc_mir/util/graphviz.rs | 14 ++++++++++- src/librustc_mir/util/mod.rs | 2 +- src/test/mir-opt/graphviz.rs | 23 +++++++++++++++++++ 10 files changed, 85 insertions(+), 40 deletions(-) create mode 100644 src/test/mir-opt/graphviz.rs diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index dde88a212408d..ace5198deaf2e 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -633,10 +633,20 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec, let body = tcx.hir().body(body_id); let cfg = cfg::CFG::new(tcx, &body); let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges; + let hir_id = code.id(); + // We have to disassemble the hir_id because name must be ASCII + // alphanumeric. This does not appear in the rendered graph, so it does not + // have to be user friendly. + let name = format!( + "hir_id_{}_{}_{}", + hir_id.owner.address_space().index(), + hir_id.owner.as_array_index(), + hir_id.local_id.index(), + ); let lcfg = LabelledCFG { tcx, cfg: &cfg, - name: format!("node_{}", code.id()), + name, labelled_edges, }; diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index c4e371d5afedb..551f18b95fe52 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -156,7 +156,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( let mut flow_inits = FlowAtLocation::new(do_dataflow( tcx, mir, - id, + def_id, &attributes, &dead_unwinds, MaybeInitializedPlaces::new(tcx, mir, &mdpe), @@ -191,7 +191,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( let flow_borrows = FlowAtLocation::new(do_dataflow( tcx, mir, - id, + def_id, &attributes, &dead_unwinds, Borrows::new(tcx, mir, regioncx.clone(), &borrow_set), @@ -200,7 +200,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( let flow_uninits = FlowAtLocation::new(do_dataflow( tcx, mir, - id, + def_id, &attributes, &dead_unwinds, MaybeUninitializedPlaces::new(tcx, mir, &mdpe), @@ -209,7 +209,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( let flow_ever_inits = FlowAtLocation::new(do_dataflow( tcx, mir, - id, + def_id, &attributes, &dead_unwinds, EverInitializedPlaces::new(tcx, mir, &mdpe), diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs index da9cc118f5521..d68377681f1ca 100644 --- a/src/librustc_mir/dataflow/graphviz.rs +++ b/src/librustc_mir/dataflow/graphviz.rs @@ -1,6 +1,6 @@ //! Hook into libgraphviz for rendering dataflow graphs for MIR. -use rustc::hir::HirId; +use rustc::hir::def_id::DefId; use rustc::mir::{BasicBlock, Mir}; use std::fs; @@ -8,13 +8,15 @@ use std::io; use std::marker::PhantomData; use std::path::Path; +use crate::util::graphviz_safe_def_name; + use super::{BitDenotation, DataflowState}; use super::DataflowBuilder; use super::DebugFormatted; pub trait MirWithFlowState<'tcx> { type BD: BitDenotation<'tcx>; - fn hir_id(&self) -> HirId; + fn def_id(&self) -> DefId; fn mir(&self) -> &Mir<'tcx>; fn flow_state(&self) -> &DataflowState<'tcx, Self::BD>; } @@ -23,7 +25,7 @@ impl<'a, 'tcx, BD> MirWithFlowState<'tcx> for DataflowBuilder<'a, 'tcx, BD> where BD: BitDenotation<'tcx> { type BD = BD; - fn hir_id(&self) -> HirId { self.hir_id } + fn def_id(&self) -> DefId { self.def_id } fn mir(&self) -> &Mir<'tcx> { self.flow_state.mir() } fn flow_state(&self) -> &DataflowState<'tcx, Self::BD> { &self.flow_state.flow_state } } @@ -47,8 +49,8 @@ pub(crate) fn print_borrowck_graph_to<'a, 'tcx, BD, P>( let g = Graph { mbcx, phantom: PhantomData, render_idx }; let mut v = Vec::new(); dot::render(&g, &mut v)?; - debug!("print_borrowck_graph_to path: {} hir_id: {}", - path.display(), mbcx.hir_id); + debug!("print_borrowck_graph_to path: {} def_id: {:?}", + path.display(), mbcx.def_id); fs::write(path, v) } @@ -69,9 +71,8 @@ impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P> type Node = Node; type Edge = Edge; fn graph_id(&self) -> dot::Id<'_> { - dot::Id::new(format!("graph_for_node_{}", - self.mbcx.hir_id())) - .unwrap() + let name = graphviz_safe_def_name(self.mbcx.def_id()); + dot::Id::new(format!("graph_for_def_id_{}", name)).unwrap() } fn node_id(&self, n: &Node) -> dot::Id<'_> { diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index 03f8ac6743617..d0035bf7d3bc2 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -4,7 +4,7 @@ use rustc_data_structures::bit_set::{BitSet, BitSetOperator, HybridBitSet}; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::work_queue::WorkQueue; -use rustc::hir::HirId; +use rustc::hir::def_id::DefId; use rustc::ty::{self, TyCtxt}; use rustc::mir::{self, Mir, BasicBlock, BasicBlockData, Location, Statement, Terminator}; use rustc::mir::traversal; @@ -39,7 +39,7 @@ pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD> where BD: BitDenotation<'tcx> { - hir_id: HirId, + def_id: DefId, flow_state: DataflowAnalysis<'a, 'tcx, BD>, print_preflow_to: Option, print_postflow_to: Option, @@ -117,7 +117,7 @@ pub struct MoveDataParamEnv<'gcx, 'tcx> { pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, - hir_id: HirId, + def_id: DefId, attributes: &[ast::Attribute], dead_unwinds: &BitSet, bd: BD, @@ -127,14 +127,14 @@ pub(crate) fn do_dataflow<'a, 'gcx, 'tcx, BD, P>(tcx: TyCtxt<'a, 'gcx, 'tcx>, P: Fn(&BD, BD::Idx) -> DebugFormatted { let flow_state = DataflowAnalysis::new(mir, dead_unwinds, bd); - flow_state.run(tcx, hir_id, attributes, p) + flow_state.run(tcx, def_id, attributes, p) } impl<'a, 'gcx: 'tcx, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitDenotation<'tcx> { pub(crate) fn run

(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - hir_id: HirId, + def_id: DefId, attributes: &[ast::Attribute], p: P) -> DataflowResults<'tcx, BD> where P: Fn(&BD, BD::Idx) -> DebugFormatted @@ -159,7 +159,7 @@ impl<'a, 'gcx: 'tcx, 'tcx: 'a, BD> DataflowAnalysis<'a, 'tcx, BD> where BD: BitD name_found(tcx.sess, attributes, "borrowck_graphviz_postflow"); let mut mbcx = DataflowBuilder { - hir_id, + def_id, print_preflow_to, print_postflow_to, flow_state: self, }; diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 32c027d90a0ce..3b0db48a94f18 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -28,7 +28,7 @@ impl MirPass for ElaborateDrops { { debug!("elaborate_drops({:?} @ {:?})", src, mir.span); - let id = tcx.hir().as_local_hir_id(src.def_id()).unwrap(); + let def_id = src.def_id(); let param_env = tcx.param_env(src.def_id()).with_reveal_all(); let move_data = match MoveData::gather_moves(mir, tcx) { Ok(move_data) => move_data, @@ -50,13 +50,13 @@ impl MirPass for ElaborateDrops { move_data, param_env, }; - let dead_unwinds = find_dead_unwinds(tcx, mir, id, &env); + let dead_unwinds = find_dead_unwinds(tcx, mir, def_id, &env); let flow_inits = - do_dataflow(tcx, mir, id, &[], &dead_unwinds, + do_dataflow(tcx, mir, def_id, &[], &dead_unwinds, MaybeInitializedPlaces::new(tcx, mir, &env), |bd, p| DebugFormatted::new(&bd.move_data().move_paths[p])); let flow_uninits = - do_dataflow(tcx, mir, id, &[], &dead_unwinds, + do_dataflow(tcx, mir, def_id, &[], &dead_unwinds, MaybeUninitializedPlaces::new(tcx, mir, &env), |bd, p| DebugFormatted::new(&bd.move_data().move_paths[p])); @@ -80,7 +80,7 @@ impl MirPass for ElaborateDrops { fn find_dead_unwinds<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, - id: hir::HirId, + def_id: hir::def_id::DefId, env: &MoveDataParamEnv<'tcx, 'tcx>) -> BitSet { @@ -89,7 +89,7 @@ fn find_dead_unwinds<'a, 'tcx>( // reach cleanup blocks, which can't have unwind edges themselves. let mut dead_unwinds = BitSet::new_empty(mir.basic_blocks().len()); let flow_inits = - do_dataflow(tcx, mir, id, &[], &dead_unwinds, + do_dataflow(tcx, mir, def_id, &[], &dead_unwinds, MaybeInitializedPlaces::new(tcx, mir, &env), |bd, p| DebugFormatted::new(&bd.move_data().move_paths[p])); for (bb, bb_data) in mir.basic_blocks().iter_enumerated() { diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 1f59802f8c6c0..98dcc3a16f209 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -383,13 +383,13 @@ fn locals_live_across_suspend_points( FxHashMap, ) { let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len()); - let hir_id = tcx.hir().as_local_hir_id(source.def_id()).unwrap(); + let def_id = source.def_id(); // Calculate when MIR locals have live storage. This gives us an upper bound of their // lifetimes. let storage_live_analysis = MaybeStorageLive::new(mir); let storage_live = - do_dataflow(tcx, mir, hir_id, &[], &dead_unwinds, storage_live_analysis, + do_dataflow(tcx, mir, def_id, &[], &dead_unwinds, storage_live_analysis, |bd, p| DebugFormatted::new(&bd.mir().local_decls[p])); // Find the MIR locals which do not use StorageLive/StorageDead statements. @@ -403,7 +403,7 @@ fn locals_live_across_suspend_points( let borrowed_locals = if !movable { let analysis = HaveBeenBorrowedLocals::new(mir); let result = - do_dataflow(tcx, mir, hir_id, &[], &dead_unwinds, analysis, + do_dataflow(tcx, mir, def_id, &[], &dead_unwinds, analysis, |bd, p| DebugFormatted::new(&bd.mir().local_decls[p])); Some((analysis, result)) } else { diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index f9f8abbe6c065..246f876235d71 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -3,7 +3,7 @@ use syntax::ast; use syntax_pos::Span; use rustc::ty::{self, TyCtxt}; -use rustc::hir; +use rustc::hir::def_id::DefId; use rustc::mir::{self, Mir, Location}; use rustc_data_structures::bit_set::BitSet; use crate::transform::{MirPass, MirSource}; @@ -27,7 +27,6 @@ impl MirPass for SanityCheck { fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource<'tcx>, mir: &mut Mir<'tcx>) { let def_id = src.def_id(); - let id = tcx.hir().as_local_hir_id(def_id).unwrap(); if !tcx.has_attr(def_id, "rustc_mir") { debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); return; @@ -41,26 +40,26 @@ impl MirPass for SanityCheck { let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len()); let flow_inits = - do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, + do_dataflow(tcx, mir, def_id, &attributes, &dead_unwinds, MaybeInitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); let flow_uninits = - do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, + do_dataflow(tcx, mir, def_id, &attributes, &dead_unwinds, MaybeUninitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); let flow_def_inits = - do_dataflow(tcx, mir, id, &attributes, &dead_unwinds, + do_dataflow(tcx, mir, def_id, &attributes, &dead_unwinds, DefinitelyInitializedPlaces::new(tcx, mir, &mdpe), |bd, i| DebugFormatted::new(&bd.move_data().move_paths[i])); if has_rustc_mir_with(&attributes, "rustc_peek_maybe_init").is_some() { - sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_inits); + sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_inits); } if has_rustc_mir_with(&attributes, "rustc_peek_maybe_uninit").is_some() { - sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_uninits); + sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_uninits); } if has_rustc_mir_with(&attributes, "rustc_peek_definite_init").is_some() { - sanity_check_via_rustc_peek(tcx, mir, id, &attributes, &flow_def_inits); + sanity_check_via_rustc_peek(tcx, mir, def_id, &attributes, &flow_def_inits); } if has_rustc_mir_with(&attributes, "stop_after_dataflow").is_some() { tcx.sess.fatal("stop_after_dataflow ended compilation"); @@ -86,12 +85,12 @@ impl MirPass for SanityCheck { /// errors are not intended to be used for unit tests.) pub fn sanity_check_via_rustc_peek<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &Mir<'tcx>, - id: hir::HirId, + def_id: DefId, _attributes: &[ast::Attribute], results: &DataflowResults<'tcx, O>) where O: BitDenotation<'tcx, Idx=MovePathIndex> + HasMoveData<'tcx> { - debug!("sanity_check_via_rustc_peek id: {:?}", id); + debug!("sanity_check_via_rustc_peek def_id: {:?}", def_id); // FIXME: this is not DRY. Figure out way to abstract this and // `dataflow::build_sets`. (But note it is doing non-standard // stuff, so such generalization may not be realistic.) diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs index 69a2adcfce026..f87714b58c442 100644 --- a/src/librustc_mir/util/graphviz.rs +++ b/src/librustc_mir/util/graphviz.rs @@ -1,6 +1,7 @@ use rustc::hir::def_id::DefId; use rustc::mir::*; use rustc::ty::TyCtxt; +use rustc_data_structures::indexed_vec::Idx; use std::fmt::Debug; use std::io::{self, Write}; @@ -20,6 +21,17 @@ pub fn write_mir_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>, Ok(()) } +// Must match `[0-9A-Za-z_]*`. This does not appear in the rendered graph, so +// it does not have to be user friendly. +pub fn graphviz_safe_def_name(def_id: DefId) -> String { + format!( + "{}_{}_{}", + def_id.krate.index(), + def_id.index.address_space().index(), + def_id.index.as_array_index(), + ) +} + /// Write a graphviz DOT graph of the MIR. pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>, def_id: DefId, @@ -27,7 +39,7 @@ pub fn write_mir_fn_graphviz<'tcx, W>(tcx: TyCtxt<'_, '_, 'tcx>, w: &mut W) -> io::Result<()> where W: Write { - writeln!(w, "digraph Mir_{} {{", tcx.hir().as_local_hir_id(def_id).unwrap())?; + writeln!(w, "digraph Mir_{} {{", graphviz_safe_def_name(def_id))?; // Global graph properties writeln!(w, r#" graph [fontname="monospace"];"#)?; diff --git a/src/librustc_mir/util/mod.rs b/src/librustc_mir/util/mod.rs index 29614a33f8e27..1a5a2a92247dd 100644 --- a/src/librustc_mir/util/mod.rs +++ b/src/librustc_mir/util/mod.rs @@ -15,7 +15,7 @@ pub mod collect_writes; pub use self::alignment::is_disaligned; pub use self::pretty::{dump_enabled, dump_mir, write_mir_pretty, PassWhere}; -pub use self::graphviz::{write_mir_graphviz}; +pub use self::graphviz::{graphviz_safe_def_name, write_mir_graphviz}; pub use self::graphviz::write_node_label as write_graphviz_node_label; /// If possible, suggest replacing `ref` with `ref mut`. diff --git a/src/test/mir-opt/graphviz.rs b/src/test/mir-opt/graphviz.rs new file mode 100644 index 0000000000000..660576996e5d4 --- /dev/null +++ b/src/test/mir-opt/graphviz.rs @@ -0,0 +1,23 @@ +// Test graphviz output +// compile-flags: -Z dump-mir-graphviz + +// ignore-tidy-linelength + +fn main() {} + +// END RUST SOURCE +// START rustc.main.mir_map.0.dot +// digraph Mir_0_0_3 { // The name here MUST be an ASCII identifier. +// graph [fontname="monospace"]; +// node [fontname="monospace"]; +// edge [fontname="monospace"]; +// label=>; +// bb0 [shape="none", label=<
0
_0 = ()
goto
+// >]; +// bb1 [shape="none", label=<
1
resume
+// >]; +// bb2 [shape="none", label=<
2
return
+// >]; +// bb0 -> bb2 [label=""]; +// } +// END rustc.main.mir_map.0.dot From 830c98d7fa4da9381d3ee9c8b918bc5dff11c378 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Sat, 16 Mar 2019 18:07:58 +0100 Subject: [PATCH 07/12] Fix undefined behavior in hint::spin_loop for x86 targets without SSE2 The pause instruction requires SSE2 but was being unconditionally used on targets without it, resulting in undefined behavior. This PR fixes that by only using the pause intrinsic if SSE2 is available. It also removes the inline assembly which was not required since these instructions are available in core::arch, and extends support of the spin_loop hint to arm targets with the v6 feature which also support the yield instruction. Closes #59237 . --- src/libcore/hint.rs | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs index 89de5c1bc8af8..b2f82ef0d175c 100644 --- a/src/libcore/hint.rs +++ b/src/libcore/hint.rs @@ -62,13 +62,32 @@ pub unsafe fn unreachable_unchecked() -> ! { #[inline] #[unstable(feature = "renamed_spin_loop", issue = "55002")] pub fn spin_loop() { - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - unsafe { - asm!("pause" ::: "memory" : "volatile"); + #[cfg( + all( + any(target_arch = "x86", target_arch = "x86_64"), + target_feature = "sse2" + ) + )] { + #[cfg(target_arch = "x86")] { + unsafe { crate::arch::x86::_mm_pause() }; + } + + #[cfg(target_arch = "x86_64")] { + unsafe { crate::arch::x86_64::_mm_pause() }; + } } - #[cfg(target_arch = "aarch64")] - unsafe { - asm!("yield" ::: "memory" : "volatile"); + #[cfg( + any( + target_arch = "aarch64", + all(target_arch = "arm", target_feature = "v6") + ) + )] { + #[cfg(target_arch = "aarch64")] { + unsafe { crate::arch::aarch64::__yield() }; + } + #[cfg(target_arch = "arm")] { + unsafe { crate::arch::arm::__yield() }; + } } } From d1808aa509f2291644b9dad89e883e3ec0f01400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 14 Mar 2019 19:16:31 -0700 Subject: [PATCH 08/12] Remove track_errors from check_match --- src/librustc_mir/build/matches/mod.rs | 7 ++++++- src/librustc_mir/hair/pattern/check_match.rs | 17 ++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index d3731e7c1274e..12aae2f385e8a 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -438,7 +438,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // always convert all match-pairs into bindings. self.simplify_candidate(&mut candidate); - if !candidate.match_pairs.is_empty() { + if !candidate.match_pairs.is_empty() && self.hir.tcx().sess.err_count() == 0 { + // Only abort compilation if no other errors have been emitted. This used to be a hard + // error that wouldn't be reached because `hair::pattern::check_match::check_match` + // wouldn't have let the compiler continue. In our tests this is only ever hit by + // `ui/consts/const-match-check.rs` with `--cfg eval1`, and that file already generates + // a different error before hand. span_bug!( candidate.match_pairs[0].pattern.span, "match pairs {:?} remaining after simplifying \ diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 49967df08891b..39f127c07d7d5 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -37,15 +37,14 @@ pub(crate) fn check_match<'a, 'tcx>( return Ok(()); }; - tcx.sess.track_errors(|| { - MatchVisitor { - tcx, - tables: tcx.body_tables(body_id), - region_scope_tree: &tcx.region_scope_tree(def_id), - param_env: tcx.param_env(def_id), - identity_substs: InternalSubsts::identity_for_item(tcx, def_id), - }.visit_body(tcx.hir().body(body_id)); - }) + MatchVisitor { + tcx, + tables: tcx.body_tables(body_id), + region_scope_tree: &tcx.region_scope_tree(def_id), + param_env: tcx.param_env(def_id), + identity_substs: InternalSubsts::identity_for_item(tcx, def_id), + }.visit_body(tcx.hir().body(body_id)); + Ok(()) } fn create_e0004<'a>(sess: &'a Session, sp: Span, error_message: String) -> DiagnosticBuilder<'a> { From 936dec8df3c28840982d6cacf2c0c22327fd9894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 14 Mar 2019 19:29:02 -0700 Subject: [PATCH 09/12] Continue running after `typeck_item_bodies` has failed --- src/librustc_typeck/check/mod.rs | 9 ++++----- src/test/ui/issues/issue-26217.rs | 6 +++++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index ab0e4b086bc77..9cba51741367d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -706,11 +706,10 @@ fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum -> Result<(), ErrorReported> { debug_assert!(crate_num == LOCAL_CRATE); - Ok(tcx.sess.track_errors(|| { - tcx.par_body_owners(|body_owner_def_id| { - tcx.ensure().typeck_tables_of(body_owner_def_id); - }); - })?) + tcx.par_body_owners(|body_owner_def_id| { + tcx.ensure().typeck_tables_of(body_owner_def_id); + }); + Ok(()) } fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { diff --git a/src/test/ui/issues/issue-26217.rs b/src/test/ui/issues/issue-26217.rs index a700807d7f216..05e0462190906 100644 --- a/src/test/ui/issues/issue-26217.rs +++ b/src/test/ui/issues/issue-26217.rs @@ -1,6 +1,10 @@ fn foo() where for<'a> T: 'a {} -fn main<'a>() { +fn bar<'a>() { foo::<&'a i32>(); //~^ ERROR the type `&'a i32` does not fulfill the required lifetime } + +fn main() { + bar(); +} From c89872cb7d1d9467158d17b3a7e001efd436e192 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 14 Mar 2019 19:38:20 -0700 Subject: [PATCH 10/12] Do not `track_errors` in `register_plugins` --- src/librustc_interface/passes.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 0c710fd283be8..c199829b298c0 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -323,22 +323,20 @@ pub fn register_plugins<'a>( .. } = registry; - sess.track_errors(|| { - let mut ls = sess.lint_store.borrow_mut(); - for pass in early_lint_passes { - ls.register_early_pass(Some(sess), true, false, pass); - } - for pass in late_lint_passes { - ls.register_late_pass(Some(sess), true, pass); - } + let mut ls = sess.lint_store.borrow_mut(); + for pass in early_lint_passes { + ls.register_early_pass(Some(sess), true, false, pass); + } + for pass in late_lint_passes { + ls.register_late_pass(Some(sess), true, pass); + } - for (name, (to, deprecated_name)) in lint_groups { - ls.register_group(Some(sess), true, name, deprecated_name, to); - } + for (name, (to, deprecated_name)) in lint_groups { + ls.register_group(Some(sess), true, name, deprecated_name, to); + } - *sess.plugin_llvm_passes.borrow_mut() = llvm_passes; - *sess.plugin_attributes.borrow_mut() = attributes.clone(); - })?; + *sess.plugin_llvm_passes.borrow_mut() = llvm_passes; + *sess.plugin_attributes.borrow_mut() = attributes.clone(); Ok((krate, PluginInfo { syntax_exts, From afdc38da0a682d06525c888c8198d378d72c4518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 17 Mar 2019 17:37:56 -0700 Subject: [PATCH 11/12] address review comments --- src/librustc/ty/query/mod.rs | 5 ++--- src/librustc_mir/build/matches/mod.rs | 11 ++++++----- src/librustc_mir/const_eval.rs | 5 +---- src/librustc_mir/hair/pattern/check_match.rs | 9 ++------- src/librustc_typeck/check/mod.rs | 5 +---- src/librustc_typeck/lib.rs | 2 +- 6 files changed, 13 insertions(+), 24 deletions(-) diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 2f085a973d202..a2d7815920e0b 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -272,7 +272,7 @@ rustc_query_append! { [define_queries!][ <'tcx> TypeChecking { [] fn typeck_item_bodies: - typeck_item_bodies_dep_node(CrateNum) -> Result<(), ErrorReported>, + typeck_item_bodies_dep_node(CrateNum) -> (), [] fn typeck_tables_of: TypeckTables(DefId) -> &'tcx ty::TypeckTables<'tcx>, }, @@ -325,8 +325,7 @@ rustc_query_append! { [define_queries!][ <'tcx> }, TypeChecking { - [] fn check_match: CheckMatch(DefId) - -> Result<(), ErrorReported>, + [] fn check_match: CheckMatch(DefId) -> (), /// Performs part of the privacy check and computes "access levels". [] fn privacy_access_levels: PrivacyAccessLevels(CrateNum) -> Lrc, diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 12aae2f385e8a..2c4fb5e07718c 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -438,17 +438,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // always convert all match-pairs into bindings. self.simplify_candidate(&mut candidate); - if !candidate.match_pairs.is_empty() && self.hir.tcx().sess.err_count() == 0 { + if !candidate.match_pairs.is_empty() { // Only abort compilation if no other errors have been emitted. This used to be a hard // error that wouldn't be reached because `hair::pattern::check_match::check_match` // wouldn't have let the compiler continue. In our tests this is only ever hit by // `ui/consts/const-match-check.rs` with `--cfg eval1`, and that file already generates // a different error before hand. - span_bug!( + self.hir.tcx().sess.delay_span_bug( candidate.match_pairs[0].pattern.span, - "match pairs {:?} remaining after simplifying \ - irrefutable pattern", - candidate.match_pairs + &format!( + "match pairs {:?} remaining after simplifying irrefutable pattern", + candidate.match_pairs, + ), ); } diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 79a3e0c5ee248..c78de80ac835c 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -15,7 +15,6 @@ use rustc::ty::layout::{self, LayoutOf, VariantIdx}; use rustc::ty::subst::Subst; use rustc::traits::Reveal; use rustc_data_structures::fx::FxHashMap; -use rustc::util::common::ErrorReported; use syntax::ast::Mutability; use syntax::source_map::{Span, DUMMY_SP}; @@ -619,9 +618,7 @@ pub fn const_eval_raw_provider<'a, 'tcx>( let tables = tcx.typeck_tables_of(def_id); // Do match-check before building MIR - if let Err(ErrorReported) = tcx.check_match(def_id) { - return Err(ErrorHandled::Reported) - } + tcx.check_match(def_id); if let hir::BodyOwnerKind::Const = tcx.hir().body_owner_kind_by_hir_id(id) { tcx.mir_const_qualif(def_id); diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 39f127c07d7d5..50df676aea9fb 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::ty::{self, Ty, TyCtxt, TyKind}; use rustc::ty::subst::{InternalSubsts, SubstsRef}; use rustc::lint; use rustc_errors::{Applicability, DiagnosticBuilder}; -use rustc::util::common::ErrorReported; use rustc::hir::def::*; use rustc::hir::def_id::DefId; @@ -27,14 +26,11 @@ use std::slice; use syntax::ptr::P; use syntax_pos::{Span, DUMMY_SP, MultiSpan}; -pub(crate) fn check_match<'a, 'tcx>( - tcx: TyCtxt<'a, 'tcx, 'tcx>, - def_id: DefId, -) -> Result<(), ErrorReported> { +pub(crate) fn check_match<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { let body_id = if let Some(id) = tcx.hir().as_local_hir_id(def_id) { tcx.hir().body_owned_by(id) } else { - return Ok(()); + return; }; MatchVisitor { @@ -44,7 +40,6 @@ pub(crate) fn check_match<'a, 'tcx>( param_env: tcx.param_env(def_id), identity_substs: InternalSubsts::identity_for_item(tcx, def_id), }.visit_body(tcx.hir().body(body_id)); - Ok(()) } fn create_e0004<'a>(sess: &'a Session, sp: Span, error_message: String) -> DiagnosticBuilder<'a> { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9cba51741367d..06ae097d9f080 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -702,14 +702,11 @@ fn check_mod_item_types<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) tcx.hir().visit_item_likes_in_module(module_def_id, &mut CheckItemTypesVisitor { tcx }); } -fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) - -> Result<(), ErrorReported> -{ +fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) { debug_assert!(crate_num == LOCAL_CRATE); tcx.par_body_owners(|body_owner_def_id| { tcx.ensure().typeck_tables_of(body_owner_def_id); }); - Ok(()) } fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index cbed7d26a9950..b2c2b233c81ab 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -363,7 +363,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) }) })?; - time(tcx.sess, "item-bodies checking", || tcx.typeck_item_bodies(LOCAL_CRATE))?; + time(tcx.sess, "item-bodies checking", || tcx.typeck_item_bodies(LOCAL_CRATE)); check_unused::check_crate(tcx); check_for_entry_fn(tcx); From 57236324ee7c914b7446f6c09057b4e06c4210b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 22 Mar 2019 20:29:28 -0700 Subject: [PATCH 12/12] Add note to address check_match errors --- src/librustc_mir/build/matches/mod.rs | 6 +++--- src/librustc_mir/const_eval.rs | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 2c4fb5e07718c..be3d730c61a1d 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -439,9 +439,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { self.simplify_candidate(&mut candidate); if !candidate.match_pairs.is_empty() { - // Only abort compilation if no other errors have been emitted. This used to be a hard - // error that wouldn't be reached because `hair::pattern::check_match::check_match` - // wouldn't have let the compiler continue. In our tests this is only ever hit by + // ICE if no other errors have been emitted. This used to be a hard error that wouldn't + // be reached because `hair::pattern::check_match::check_match` wouldn't have let the + // compiler continue. In our tests this is only ever hit by // `ui/consts/const-match-check.rs` with `--cfg eval1`, and that file already generates // a different error before hand. self.hir.tcx().sess.delay_span_bug( diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index c78de80ac835c..2e15f0de69f70 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -618,6 +618,7 @@ pub fn const_eval_raw_provider<'a, 'tcx>( let tables = tcx.typeck_tables_of(def_id); // Do match-check before building MIR + // FIXME(#59378) check_match may have errored but we're not checking for that anymore tcx.check_match(def_id); if let hir::BodyOwnerKind::Const = tcx.hir().body_owner_kind_by_hir_id(id) {