diff --git a/Cargo.lock b/Cargo.lock index c071a2e11d269..1a586122e17ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1520,7 +1520,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "minifier" -version = "0.0.28" +version = "0.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3039,7 +3039,7 @@ dependencies = [ name = "rustdoc" version = "0.0.0" dependencies = [ - "minifier 0.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "minifier 0.0.29 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4149,7 +4149,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16" "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum minifier 0.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "3a2898502751dcc9d66b6fff57f3cf63cc91605e83e1a33515396f5027f8e4ca" +"checksum minifier 0.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4950cb2617b1933e2da0446e864dfe0d6a22c22ff72297996c46e6a63b210b" "checksum miniz-sys 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "0300eafb20369952951699b68243ab4334f4b10a88f411c221d444b36c40e649" "checksum miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c" "checksum miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28edaef377517fd9fe3e085c37d892ce7acd1fbeab9239c5a36eec352d8a8b7e" diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 8d3c8fc435c8d..522466314d660 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -634,7 +634,28 @@ impl<'a> Builder<'a> { if compiler.is_snapshot(self) { self.rustc_snapshot_libdir() } else { - self.sysroot(compiler).join(libdir(&compiler.host)) + match self.config.libdir_relative() { + Some(relative_libdir) if compiler.stage >= 1 + => self.sysroot(compiler).join(relative_libdir), + _ => self.sysroot(compiler).join(libdir(&compiler.host)) + } + } + } + + /// Returns the compiler's relative libdir where it stores the dynamic libraries that + /// it itself links against. + /// + /// For example this returns `lib` on Unix and `bin` on + /// Windows. + pub fn libdir_relative(&self, compiler: Compiler) -> &Path { + if compiler.is_snapshot(self) { + libdir(&self.config.build).as_ref() + } else { + match self.config.libdir_relative() { + Some(relative_libdir) if compiler.stage >= 1 + => relative_libdir, + _ => libdir(&compiler.host).as_ref() + } } } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 237f5c0ea2f15..08316b71ea85b 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -20,7 +20,7 @@ use filetime::FileTime; use serde_json; use crate::dist; -use crate::util::{exe, libdir, is_dylib}; +use crate::util::{exe, is_dylib}; use crate::{Compiler, Mode, GitRepo}; use crate::native; @@ -1005,13 +1005,13 @@ impl Step for Assemble { // Link in all dylibs to the libdir let sysroot = builder.sysroot(target_compiler); - let sysroot_libdir = sysroot.join(libdir(&*host)); - t!(fs::create_dir_all(&sysroot_libdir)); + let rustc_libdir = builder.rustc_libdir(target_compiler); + t!(fs::create_dir_all(&rustc_libdir)); let src_libdir = builder.sysroot_libdir(build_compiler, host); for f in builder.read_dir(&src_libdir) { let filename = f.file_name().into_string().unwrap(); if is_dylib(&filename) { - builder.copy(&f.path(), &sysroot_libdir.join(&filename)); + builder.copy(&f.path(), &rustc_libdir.join(&filename)); } } diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index d982330a61640..a4d924d64ee78 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -18,7 +18,7 @@ use build_helper::output; use crate::{Compiler, Mode, LLVM_TOOLS}; use crate::channel; -use crate::util::{libdir, is_dylib, exe}; +use crate::util::{is_dylib, exe}; use crate::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::compile; use crate::tool::{self, Tool}; @@ -473,7 +473,7 @@ impl Step for Rustc { fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) { let host = compiler.host; let src = builder.sysroot(compiler); - let libdir = libdir(&host); + let libdir = builder.rustc_libdir(compiler); // Copy rustc/rustdoc binaries t!(fs::create_dir_all(image.join("bin"))); @@ -481,13 +481,15 @@ impl Step for Rustc { builder.install(&builder.rustdoc(compiler), &image.join("bin"), 0o755); + let libdir_relative = builder.libdir_relative(compiler); + // Copy runtime DLLs needed by the compiler - if libdir != "bin" { - for entry in builder.read_dir(&src.join(libdir)) { + if libdir_relative.to_str() != Some("bin") { + for entry in builder.read_dir(&libdir) { let name = entry.file_name(); if let Some(s) = name.to_str() { if is_dylib(s) { - builder.install(&entry.path(), &image.join(libdir), 0o644); + builder.install(&entry.path(), &image.join(&libdir_relative), 0o644); } } } @@ -516,7 +518,8 @@ impl Step for Rustc { .join("bin") .join(&exe); // for the rationale about this rename check `compile::copy_lld_to_sysroot` - let dst = image.join("lib/rustlib") + let dst = image.join(libdir_relative) + .join("rustlib") .join(&*host) .join("bin") .join(&exe); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 2394ae7fb7913..47ac04baf6d6d 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -1275,6 +1275,7 @@ impl Build { fn install(&self, src: &Path, dstdir: &Path, perms: u32) { if self.config.dry_run { return; } let dst = dstdir.join(src.file_name().unwrap()); + self.verbose_than(1, &format!("Install {:?} to {:?}", src, dst)); t!(fs::create_dir_all(dstdir)); drop(fs::remove_file(&dst)); { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 3703ea08b6253..1934f800af757 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1352,7 +1352,7 @@ impl<'a> NameBinding<'a> { } } - // We sometimes need to treat variants as `pub` for backwards compatibility + // We sometimes need to treat variants as `pub` for backwards compatibility. fn pseudo_vis(&self) -> ty::Visibility { if self.is_variant() && self.def().def_id().is_local() { ty::Visibility::Public @@ -2714,7 +2714,7 @@ impl<'a> Resolver<'a> { { let mut self_type_rib = Rib::new(NormalRibKind); - // plain insert (no renaming, types are not currently hygienic....) + // Plain insert (no renaming, since types are not currently hygienic) self_type_rib.bindings.insert(keywords::SelfUpper.ident(), self_def); self.ribs[TypeNS].push(self_type_rib); f(self); @@ -4438,26 +4438,47 @@ impl<'a> Resolver<'a> { let mut collected_traits = Vec::new(); module.for_each_child(|name, ns, binding| { if ns != TypeNS { return } - if let Def::Trait(_) = binding.def() { - collected_traits.push((name, binding)); + match binding.def() { + Def::Trait(_) | + Def::TraitAlias(_) => collected_traits.push((name, binding)), + _ => (), } }); *traits = Some(collected_traits.into_boxed_slice()); } for &(trait_name, binding) in traits.as_ref().unwrap().iter() { - let module = binding.module().unwrap(); - let mut ident = ident; - if ident.span.glob_adjust(module.expansion, binding.span.ctxt().modern()).is_none() { - continue - } - if self.resolve_ident_in_module_unadjusted( - ModuleOrUniformRoot::Module(module), - ident, - ns, - false, - module.span, - ).is_ok() { + // Traits have pseudo-modules that can be used to search for the given ident. + if let Some(module) = binding.module() { + let mut ident = ident; + if ident.span.glob_adjust( + module.expansion, + binding.span.ctxt().modern(), + ).is_none() { + continue + } + if self.resolve_ident_in_module_unadjusted( + ModuleOrUniformRoot::Module(module), + ident, + ns, + false, + module.span, + ).is_ok() { + let import_id = match binding.kind { + NameBindingKind::Import { directive, .. } => { + self.maybe_unused_trait_imports.insert(directive.id); + self.add_to_glob_map(&directive, trait_name); + Some(directive.id) + } + _ => None, + }; + let trait_def_id = module.def_id().unwrap(); + found_traits.push(TraitCandidate { def_id: trait_def_id, import_id }); + } + } else if let Def::TraitAlias(_) = binding.def() { + // For now, just treat all trait aliases as possible candidates, since we don't + // know if the ident is somewhere in the transitive bounds. + let import_id = match binding.kind { NameBindingKind::Import { directive, .. } => { self.maybe_unused_trait_imports.insert(directive.id); @@ -4466,8 +4487,10 @@ impl<'a> Resolver<'a> { } _ => None, }; - let trait_def_id = module.def_id().unwrap(); - found_traits.push(TraitCandidate { def_id: trait_def_id, import_id: import_id }); + let trait_def_id = binding.def().def_id(); + found_traits.push(TraitCandidate { def_id: trait_def_id, import_id }); + } else { + bug!("candidate is not trait or trait alias?") } } } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 7ea07f5e0cbcb..97b630ba5f298 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -1334,7 +1334,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { self.populate_module_if_necessary(module); - if let Some(Def::Trait(_)) = module.def() { + if module.is_trait() { self.session.span_err(directive.span, "items in traits are not importable."); return; } else if module.def_id() == directive.parent_scope.module.def_id() { diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 40dd621733594..42156213f21df 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -896,20 +896,36 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let trait_substs = self.fresh_item_substs(trait_def_id); let trait_ref = ty::TraitRef::new(trait_def_id, trait_substs); - for item in self.impl_or_trait_item(trait_def_id) { - // Check whether `trait_def_id` defines a method with suitable name: - if !self.has_applicable_self(&item) { - debug!("method has inapplicable self"); - self.record_static_candidate(TraitSource(trait_def_id)); - continue; - } + if self.tcx.is_trait_alias(trait_def_id) { + // For trait aliases, assume all super-traits are relevant. + let bounds = iter::once(trait_ref.to_poly_trait_ref()); + self.elaborate_bounds(bounds, |this, new_trait_ref, item| { + let new_trait_ref = this.erase_late_bound_regions(&new_trait_ref); + + let (xform_self_ty, xform_ret_ty) = + this.xform_self_ty(&item, new_trait_ref.self_ty(), new_trait_ref.substs); + this.push_candidate(Candidate { + xform_self_ty, xform_ret_ty, item, import_id, + kind: TraitCandidate(new_trait_ref), + }, true); + }); + } else { + debug_assert!(self.tcx.is_trait(trait_def_id)); + for item in self.impl_or_trait_item(trait_def_id) { + // Check whether `trait_def_id` defines a method with suitable name. + if !self.has_applicable_self(&item) { + debug!("method has inapplicable self"); + self.record_static_candidate(TraitSource(trait_def_id)); + continue; + } - let (xform_self_ty, xform_ret_ty) = - self.xform_self_ty(&item, trait_ref.self_ty(), trait_substs); - self.push_candidate(Candidate { - xform_self_ty, xform_ret_ty, item, import_id, - kind: TraitCandidate(trait_ref), - }, false); + let (xform_self_ty, xform_ret_ty) = + self.xform_self_ty(&item, trait_ref.self_ty(), trait_substs); + self.push_candidate(Candidate { + xform_self_ty, xform_ret_ty, item, import_id, + kind: TraitCandidate(trait_ref), + }, false); + } } Ok(()) } @@ -930,7 +946,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { .filter(|&name| set.insert(name)) .collect(); - // sort them by the name so we have a stable result + // Sort them by the name so we have a stable result. names.sort_by_cached_key(|n| n.as_str()); names } @@ -945,6 +961,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { return r; } + debug!("pick: actual search failed, assemble diagnotics"); + let static_candidates = mem::replace(&mut self.static_candidates, vec![]); let private_candidate = self.private_candidate.take(); let unsatisfied_predicates = mem::replace(&mut self.unsatisfied_predicates, vec![]); diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index fde0e47650d80..5f5c7cfec9578 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -757,9 +757,13 @@ fn compute_all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec impl<'v, 'a, 'tcx> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a, 'tcx> { fn visit_item(&mut self, i: &'v hir::Item) { - if let hir::ItemKind::Trait(..) = i.node { - let def_id = self.map.local_def_id_from_hir_id(i.hir_id); - self.traits.push(def_id); + match i.node { + hir::ItemKind::Trait(..) | + hir::ItemKind::TraitAlias(..) => { + let def_id = self.map.local_def_id_from_hir_id(i.hir_id); + self.traits.push(def_id); + } + _ => () } } @@ -781,7 +785,8 @@ fn compute_all_traits<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Vec external_mods: &mut FxHashSet, def: Def) { match def { - Def::Trait(def_id) => { + Def::Trait(def_id) | + Def::TraitAlias(def_id) => { traits.push(def_id); } Def::Mod(def_id) => { diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index a8c9166591d85..4d2c03a4f2fdb 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -10,6 +10,6 @@ path = "lib.rs" [dependencies] pulldown-cmark = { version = "0.1.2", default-features = false } -minifier = "0.0.28" +minifier = "0.0.29" tempfile = "3" parking_lot = "0.7" diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index f7e8cdeaeca89..de434e9d2e36c 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -965,7 +965,11 @@ themePicker.onblur = handleThemeButtonsBlur; if for_search_index && line.starts_with("var R") { variables.push(line.clone()); // We need to check if the crate name has been put into a variable as well. - let tokens = js::simple_minify(&line).apply(js::clean_tokens); + let tokens: js::Tokens<'_> = js::simple_minify(&line) + .into_iter() + .filter(js::clean_token) + .collect::>() + .into(); let mut pos = 0; while pos < tokens.len() { if let Some((var_pos, Some(value_pos))) = @@ -1288,46 +1292,51 @@ fn write_minify_replacer( contents: &str, enable_minification: bool, ) -> io::Result<()> { - use minifier::js::{Keyword, ReservedChar, Token}; + use minifier::js::{simple_minify, Keyword, ReservedChar, Token, Tokens}; if enable_minification { writeln!(dst, "{}", - minifier::js::simple_minify(contents) - .apply(|f| { - // We keep backlines. - minifier::js::clean_tokens_except(f, |c| { - c.get_char() != Some(ReservedChar::Backline) - }) - }) - .apply(|f| { - minifier::js::replace_token_with(f, |t| { - match *t { - Token::Keyword(Keyword::Null) => Some(Token::Other("N")), - Token::String(s) => { - let s = &s[1..s.len() -1]; // The quotes are included - if s.is_empty() { - Some(Token::Other("E")) - } else if s == "t" { - Some(Token::Other("T")) - } else if s == "u" { - Some(Token::Other("U")) - } else { - None - } - } - _ => None, - } - }) - }) - .apply(|f| { - // We add a backline after the newly created variables. - minifier::js::aggregate_strings_into_array_with_separation( - f, - "R", - Token::Char(ReservedChar::Backline), - ) - }) - .to_string()) + { + let tokens: Tokens<'_> = simple_minify(contents) + .into_iter() + .filter(|f| { + // We keep backlines. + minifier::js::clean_token_except(f, &|c: &Token<'_>| { + c.get_char() != Some(ReservedChar::Backline) + }) + }) + .map(|f| { + minifier::js::replace_token_with(f, &|t: &Token<'_>| { + match *t { + Token::Keyword(Keyword::Null) => Some(Token::Other("N")), + Token::String(s) => { + let s = &s[1..s.len() -1]; // The quotes are included + if s.is_empty() { + Some(Token::Other("E")) + } else if s == "t" { + Some(Token::Other("T")) + } else if s == "u" { + Some(Token::Other("U")) + } else { + None + } + } + _ => None, + } + }) + }) + .collect::>() + .into(); + tokens.apply(|f| { + // We add a backline after the newly created variables. + minifier::js::aggregate_strings_into_array_with_separation( + f, + "R", + Token::Char(ReservedChar::Backline), + ) + }) + .to_string() + }) } else { writeln!(dst, "{}", contents) } diff --git a/src/libstd/sys/sgx/abi/mod.rs b/src/libstd/sys/sgx/abi/mod.rs index 85ec8be4aae69..1f433e25ee16c 100644 --- a/src/libstd/sys/sgx/abi/mod.rs +++ b/src/libstd/sys/sgx/abi/mod.rs @@ -69,9 +69,9 @@ extern "C" fn entry(p1: u64, p2: u64, p3: u64, secondary: bool, p4: u64, p5: u64 } // check entry is being called according to ABI - assert_eq!(p3, 0); - assert_eq!(p4, 0); - assert_eq!(p5, 0); + rtassert!(p3 == 0); + rtassert!(p4 == 0); + rtassert!(p5 == 0); unsafe { // The actual types of these arguments are `p1: *const Arg, p2: diff --git a/src/libstd/sys/sgx/abi/reloc.rs b/src/libstd/sys/sgx/abi/reloc.rs index a39841bc36f53..6dd24c524fc30 100644 --- a/src/libstd/sys/sgx/abi/reloc.rs +++ b/src/libstd/sys/sgx/abi/reloc.rs @@ -23,7 +23,7 @@ pub fn relocate_elf_rela() { }; for rela in relas { if rela.info != (/*0 << 32 |*/ R_X86_64_RELATIVE as u64) { - panic!("Invalid relocation"); + rtabort!("Invalid relocation"); } unsafe { *mem::rel_ptr_mut::<*const ()>(rela.offset) = mem::rel_ptr(rela.addend) }; } diff --git a/src/libstd/sys/sgx/abi/tls.rs b/src/libstd/sys/sgx/abi/tls.rs index fa82e8ccf0588..03e08ad547d36 100644 --- a/src/libstd/sys/sgx/abi/tls.rs +++ b/src/libstd/sys/sgx/abi/tls.rs @@ -100,20 +100,24 @@ impl Tls { } pub fn create(dtor: Option) -> Key { - let index = TLS_KEY_IN_USE.set().expect("TLS limit exceeded"); + let index = if let Some(index) = TLS_KEY_IN_USE.set() { + index + } else { + rtabort!("TLS limit exceeded") + }; TLS_DESTRUCTOR[index].store(dtor.map_or(0, |f| f as usize), Ordering::Relaxed); Key::from_index(index) } pub fn set(key: Key, value: *mut u8) { let index = key.to_index(); - assert!(TLS_KEY_IN_USE.get(index)); + rtassert!(TLS_KEY_IN_USE.get(index)); unsafe { Self::current() }.data[index].set(value); } pub fn get(key: Key) -> *mut u8 { let index = key.to_index(); - assert!(TLS_KEY_IN_USE.get(index)); + rtassert!(TLS_KEY_IN_USE.get(index)); unsafe { Self::current() }.data[index].get() } diff --git a/src/libstd/sys/sgx/abi/usercalls/alloc.rs b/src/libstd/sys/sgx/abi/usercalls/alloc.rs index ec9c30a3e4f9d..22ae2a8e07d31 100644 --- a/src/libstd/sys/sgx/abi/usercalls/alloc.rs +++ b/src/libstd/sys/sgx/abi/usercalls/alloc.rs @@ -190,11 +190,15 @@ impl User where T: UserSafe { unsafe { // Mustn't call alloc with size 0. let ptr = if size > 0 { - super::alloc(size, T::align_of()).expect("User memory allocation failed") as _ + rtunwrap!(Ok, super::alloc(size, T::align_of())) as _ } else { T::align_of() as _ // dangling pointer ok for size 0 }; - User(NonNull::new_userref(T::from_raw_sized(ptr, size))) + if let Ok(v) = crate::panic::catch_unwind(|| T::from_raw_sized(ptr, size)) { + User(NonNull::new_userref(v)) + } else { + rtabort!("Got invalid pointer from alloc() usercall") + } } } diff --git a/src/libstd/sys/sgx/abi/usercalls/mod.rs b/src/libstd/sys/sgx/abi/usercalls/mod.rs index d84b6154cbebf..0abfc26bced00 100644 --- a/src/libstd/sys/sgx/abi/usercalls/mod.rs +++ b/src/libstd/sys/sgx/abi/usercalls/mod.rs @@ -52,7 +52,7 @@ pub fn close(fd: Fd) { fn string_from_bytebuffer(buf: &alloc::UserRef, usercall: &str, arg: &str) -> String { String::from_utf8(buf.copy_user_buffer()) - .unwrap_or_else(|_| panic!("Usercall {}: expected {} to be valid UTF-8", usercall, arg)) + .unwrap_or_else(|_| rtabort!("Usercall {}: expected {} to be valid UTF-8", usercall, arg)) } /// Usercall `bind_stream`. See the ABI documentation for more information. @@ -176,7 +176,7 @@ fn check_os_error(err: Result) -> i32 { { err } else { - panic!("Usercall: returned invalid error value {}", err) + rtabort!("Usercall: returned invalid error value {}", err) } } diff --git a/src/libstd/sys/sgx/abi/usercalls/raw.rs b/src/libstd/sys/sgx/abi/usercalls/raw.rs index ad0b6d7b3d8ec..e4694a8827a0d 100644 --- a/src/libstd/sys/sgx/abi/usercalls/raw.rs +++ b/src/libstd/sys/sgx/abi/usercalls/raw.rs @@ -131,22 +131,22 @@ impl RegisterArgument for Option> { impl ReturnValue for ! { fn from_registers(call: &'static str, _regs: (Register, Register)) -> Self { - panic!("Usercall {}: did not expect to be re-entered", call); + rtabort!("Usercall {}: did not expect to be re-entered", call); } } impl ReturnValue for () { - fn from_registers(call: &'static str, regs: (Register, Register)) -> Self { - assert_eq!(regs.0, 0, "Usercall {}: expected {} return value to be 0", call, "1st"); - assert_eq!(regs.1, 0, "Usercall {}: expected {} return value to be 0", call, "2nd"); + fn from_registers(call: &'static str, usercall_retval: (Register, Register)) -> Self { + rtassert!(usercall_retval.0 == 0); + rtassert!(usercall_retval.1 == 0); () } } impl ReturnValue for T { - fn from_registers(call: &'static str, regs: (Register, Register)) -> Self { - assert_eq!(regs.1, 0, "Usercall {}: expected {} return value to be 0", call, "2nd"); - T::from_register(regs.0) + fn from_registers(call: &'static str, usercall_retval: (Register, Register)) -> Self { + rtassert!(usercall_retval.1 == 0); + T::from_register(usercall_retval.0) } } @@ -174,8 +174,7 @@ macro_rules! enclave_usercalls_internal_define_usercalls { #[inline(always)] pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3, $n4: $t4) -> $r { ReturnValue::from_registers(stringify!($f), do_usercall( - NonZeroU64::new(Usercalls::$f as Register) - .expect("Usercall number must be non-zero"), + rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)), RegisterArgument::into_register($n1), RegisterArgument::into_register($n2), RegisterArgument::into_register($n3), @@ -191,8 +190,7 @@ macro_rules! enclave_usercalls_internal_define_usercalls { #[inline(always)] pub unsafe fn $f($n1: $t1, $n2: $t2, $n3: $t3) -> $r { ReturnValue::from_registers(stringify!($f), do_usercall( - NonZeroU64::new(Usercalls::$f as Register) - .expect("Usercall number must be non-zero"), + rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)), RegisterArgument::into_register($n1), RegisterArgument::into_register($n2), RegisterArgument::into_register($n3), @@ -208,8 +206,7 @@ macro_rules! enclave_usercalls_internal_define_usercalls { #[inline(always)] pub unsafe fn $f($n1: $t1, $n2: $t2) -> $r { ReturnValue::from_registers(stringify!($f), do_usercall( - NonZeroU64::new(Usercalls::$f as Register) - .expect("Usercall number must be non-zero"), + rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)), RegisterArgument::into_register($n1), RegisterArgument::into_register($n2), 0,0, @@ -224,8 +221,7 @@ macro_rules! enclave_usercalls_internal_define_usercalls { #[inline(always)] pub unsafe fn $f($n1: $t1) -> $r { ReturnValue::from_registers(stringify!($f), do_usercall( - NonZeroU64::new(Usercalls::$f as Register) - .expect("Usercall number must be non-zero"), + rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)), RegisterArgument::into_register($n1), 0,0,0, return_type_is_abort!($r) @@ -239,8 +235,7 @@ macro_rules! enclave_usercalls_internal_define_usercalls { #[inline(always)] pub unsafe fn $f() -> $r { ReturnValue::from_registers(stringify!($f), do_usercall( - NonZeroU64::new(Usercalls::$f as Register) - .expect("Usercall number must be non-zero"), + rtunwrap!(Some, NonZeroU64::new(Usercalls::$f as Register)), 0,0,0,0, return_type_is_abort!($r) )) diff --git a/src/libstd/sys/sgx/condvar.rs b/src/libstd/sys/sgx/condvar.rs index f9a76f0baf51a..000bb19f2692a 100644 --- a/src/libstd/sys/sgx/condvar.rs +++ b/src/libstd/sys/sgx/condvar.rs @@ -32,9 +32,8 @@ impl Condvar { mutex.lock() } - 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"); + pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool { + rtabort!("timeout not supported in SGX"); } #[inline] diff --git a/src/libstd/sys/sgx/mod.rs b/src/libstd/sys/sgx/mod.rs index dc51a932c616c..b0679f65f0d68 100644 --- a/src/libstd/sys/sgx/mod.rs +++ b/src/libstd/sys/sgx/mod.rs @@ -139,7 +139,7 @@ pub fn hashmap_random_keys() -> (u64, u64) { return ret; } } - panic!("Failed to obtain random data"); + rtabort!("Failed to obtain random data"); } } (rdrand64(), rdrand64()) diff --git a/src/libstd/sys/sgx/rwlock.rs b/src/libstd/sys/sgx/rwlock.rs index 4cba36aa64dd5..09b5ffb199676 100644 --- a/src/libstd/sys/sgx/rwlock.rs +++ b/src/libstd/sys/sgx/rwlock.rs @@ -105,7 +105,7 @@ impl RWLock { *wguard.lock_var_mut() = true; } else { // No writers were waiting, the lock is released - assert!(rguard.queue_empty()); + rtassert!(rguard.queue_empty()); } } } diff --git a/src/libstd/sys/sgx/thread.rs b/src/libstd/sys/sgx/thread.rs index a3637723ba1bd..565a523ebe06f 100644 --- a/src/libstd/sys/sgx/thread.rs +++ b/src/libstd/sys/sgx/thread.rs @@ -62,17 +62,15 @@ impl Thread { } pub(super) fn entry() { - let mut guard = task_queue::lock(); - let task = guard.pop().expect("Thread started but no tasks pending"); - drop(guard); // make sure to not hold the task queue lock longer than necessary + let mut pending_tasks = task_queue::lock(); + let task = rtunwrap!(Some, pending_tasks.pop()); + drop(pending_tasks); // make sure to not hold the task queue lock longer than necessary task.run() } pub fn yield_now() { - assert_eq!( - usercalls::wait(0, usercalls::raw::WAIT_NO).unwrap_err().kind(), - io::ErrorKind::WouldBlock - ); + let wait_error = rtunwrap!(Err, usercalls::wait(0, usercalls::raw::WAIT_NO)); + rtassert!(wait_error.kind() == io::ErrorKind::WouldBlock); } pub fn set_name(_name: &CStr) { @@ -80,7 +78,7 @@ impl Thread { } pub fn sleep(_dur: Duration) { - panic!("can't sleep"); // FIXME + rtabort!("can't sleep"); // FIXME } pub fn join(self) { diff --git a/src/libstd/sys/sgx/waitqueue.rs b/src/libstd/sys/sgx/waitqueue.rs index f4adb7d1e1606..d542f9b410127 100644 --- a/src/libstd/sys/sgx/waitqueue.rs +++ b/src/libstd/sys/sgx/waitqueue.rs @@ -121,7 +121,7 @@ impl<'a, T> Drop for WaitGuard<'a, T> { NotifiedTcs::Single(tcs) => Some(tcs), NotifiedTcs::All { .. } => None }; - usercalls::send(EV_UNPARK, target_tcs).unwrap(); + rtunwrap!(Ok, usercalls::send(EV_UNPARK, target_tcs)); } } @@ -141,6 +141,7 @@ impl WaitQueue { /// /// This function does not return until this thread has been awoken. pub fn wait(mut guard: SpinMutexGuard<'_, WaitVariable>) { + // very unsafe: check requirements of UnsafeList::push unsafe { let mut entry = UnsafeListEntry::new(SpinMutex::new(WaitEntry { tcs: thread::current(), @@ -149,10 +150,9 @@ impl WaitQueue { let entry = guard.queue.inner.push(&mut entry); drop(guard); while !entry.lock().wake { - assert_eq!( - usercalls::wait(EV_UNPARK, WAIT_INDEFINITE).unwrap() & EV_UNPARK, - EV_UNPARK - ); + // don't panic, this would invalidate `entry` during unwinding + let eventset = rtunwrap!(Ok, usercalls::wait(EV_UNPARK, WAIT_INDEFINITE)); + rtassert!(eventset & EV_UNPARK == EV_UNPARK); } } } @@ -269,7 +269,7 @@ mod unsafe_list { // ,-------> /---------\ next ---, // | |head_tail| | // `--- prev \---------/ <-------` - assert_eq!(self.head_tail.as_ref().prev, first); + rtassert!(self.head_tail.as_ref().prev == first); true } else { false @@ -285,7 +285,9 @@ mod unsafe_list { /// # Safety /// /// The entry must remain allocated until the entry is removed from the - /// list AND the caller who popped is done using the entry. + /// list AND the caller who popped is done using the entry. Special + /// care must be taken in the caller of `push` to ensure unwinding does + /// not destroy the stack frame containing the entry. pub unsafe fn push<'a>(&mut self, entry: &'a mut UnsafeListEntry) -> &'a T { self.init(); @@ -303,6 +305,7 @@ mod unsafe_list { entry.as_mut().prev = prev_tail; entry.as_mut().next = self.head_tail; prev_tail.as_mut().next = entry; + // unwrap ok: always `Some` on non-dummy entries (*entry.as_ptr()).value.as_ref().unwrap() } @@ -333,6 +336,7 @@ mod unsafe_list { second.as_mut().prev = self.head_tail; first.as_mut().next = NonNull::dangling(); first.as_mut().prev = NonNull::dangling(); + // unwrap ok: always `Some` on non-dummy entries Some((*first.as_ptr()).value.as_ref().unwrap()) } } diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs index 883ab34f07c58..4c64e9f3afba7 100644 --- a/src/libstd/sys_common/mod.rs +++ b/src/libstd/sys_common/mod.rs @@ -28,6 +28,15 @@ macro_rules! rtassert { }) } +#[allow(unused_macros)] // not used on all platforms +macro_rules! rtunwrap { + ($ok:ident, $e:expr) => (if let $ok(v) = $e { + v + } else { + rtabort!(concat!("unwrap failed: ", stringify!($e))); + }) +} + pub mod alloc; pub mod at_exit_imp; #[cfg(feature = "backtrace")] diff --git a/src/test/run-pass/traits/auxiliary/trait_alias.rs b/src/test/run-pass/traits/auxiliary/trait_alias.rs new file mode 100644 index 0000000000000..9e412215512c9 --- /dev/null +++ b/src/test/run-pass/traits/auxiliary/trait_alias.rs @@ -0,0 +1,13 @@ +#![feature(trait_alias)] + +pub trait Hello { + fn hello(&self); +} + +pub struct Hi; + +impl Hello for Hi { + fn hello(&self) {} +} + +pub trait Greet = Hello; diff --git a/src/test/run-pass/traits/trait-alias-import-cross-crate.rs b/src/test/run-pass/traits/trait-alias-import-cross-crate.rs new file mode 100644 index 0000000000000..975542ab49b59 --- /dev/null +++ b/src/test/run-pass/traits/trait-alias-import-cross-crate.rs @@ -0,0 +1,14 @@ +// run-pass +// aux-build:trait_alias.rs + +#![feature(trait_alias)] + +extern crate trait_alias; + +// Import only the alias, not the real trait. +use trait_alias::{Greet, Hi}; + +fn main() { + let hi = Hi; + hi.hello(); // From `Hello`, via `Greet` alias. +} diff --git a/src/test/run-pass/traits/trait-alias-import.rs b/src/test/run-pass/traits/trait-alias-import.rs new file mode 100644 index 0000000000000..7d63320b9aad4 --- /dev/null +++ b/src/test/run-pass/traits/trait-alias-import.rs @@ -0,0 +1,38 @@ +#![feature(trait_alias)] + +mod inner { + pub trait Foo { + fn foo(&self); + } + + pub struct Qux; + + impl Foo for Qux { + fn foo(&self) {} + } + + pub trait Bar = Foo; +} + +mod two { + pub trait A { + fn foo(); + } + + impl A for u8 { + fn foo() {} + } +} + +// Import only the alias, not the `Foo` trait. +use inner::{Bar, Qux}; + +// Declaring an alias also brings in aliased methods. +trait Two = two::A; + +fn main() { + let q = Qux; + q.foo(); // From Bar. + + u8::foo(); // From A. +} diff --git a/src/test/ui/traits/trait-alias-ambiguous.rs b/src/test/ui/traits/trait-alias-ambiguous.rs new file mode 100644 index 0000000000000..28409e0c66277 --- /dev/null +++ b/src/test/ui/traits/trait-alias-ambiguous.rs @@ -0,0 +1,24 @@ +#![feature(trait_alias)] + +mod inner { + pub trait A { fn foo(&self); } + pub trait B { fn foo(&self); } + + impl A for u8 { + fn foo(&self) {} + } + impl B for u8 { + fn foo(&self) {} + } + + pub trait C = A + B; +} + +use inner::C; + +fn main() { + let t = 1u8; + t.foo(); //~ ERROR E0034 + + inner::A::foo(&t); // ok +} diff --git a/src/test/ui/traits/trait-alias-ambiguous.stderr b/src/test/ui/traits/trait-alias-ambiguous.stderr new file mode 100644 index 0000000000000..b7443269b882d --- /dev/null +++ b/src/test/ui/traits/trait-alias-ambiguous.stderr @@ -0,0 +1,20 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/trait-alias-ambiguous.rs:21:7 + | +LL | t.foo(); + | ^^^ multiple `foo` found + | +note: candidate #1 is defined in an impl of the trait `inner::A` for the type `u8` + --> $DIR/trait-alias-ambiguous.rs:8:9 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `inner::B` for the type `u8` + --> $DIR/trait-alias-ambiguous.rs:11:9 + | +LL | fn foo(&self) {} + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`.