diff --git a/RELEASES.md b/RELEASES.md index 068e9e7263e7d..fba68ce043e26 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -56,7 +56,6 @@ Stabilized APIs - [`Take::set_limit`] - [`hint::unreachable_unchecked`] - [`os::unix::process::parent_id`] -- [`process::id`] - [`ptr::swap_nonoverlapping`] - [`slice::rsplit_mut`] - [`slice::rsplit`] diff --git a/src/Cargo.lock b/src/Cargo.lock index d4544ffa3244f..5c4d099f9c94c 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2035,6 +2035,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "rustc_allocator" version = "0.0.0" dependencies = [ + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_errors 0.0.0", "rustc_target 0.0.0", diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 0c164d86332a8..0a428a61d1202 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -273,7 +273,7 @@ macro_rules! tool { /// Whether this tool requires LLVM to run pub fn uses_llvm_tools(&self) -> bool { match self { - $(Tool::$name => true $(&& $llvm)*,)+ + $(Tool::$name => false $(|| $llvm)*,)+ } } } @@ -340,9 +340,6 @@ macro_rules! tool { } } -// FIXME(#51459): We have only checked that RustInstaller does not require -// the LLVM binaries when running. We should go through all tools to determine -// if they really need LLVM binaries, and make `llvm_tools` a required argument. tool!( Rustbook, "src/tools/rustbook", "rustbook", Mode::ToolRustc; ErrorIndex, "src/tools/error_index_generator", "error_index_generator", Mode::ToolRustc; @@ -350,10 +347,10 @@ tool!( Tidy, "src/tools/tidy", "tidy", Mode::ToolStd; Linkchecker, "src/tools/linkchecker", "linkchecker", Mode::ToolStd; CargoTest, "src/tools/cargotest", "cargotest", Mode::ToolStd; - Compiletest, "src/tools/compiletest", "compiletest", Mode::ToolTest; + Compiletest, "src/tools/compiletest", "compiletest", Mode::ToolTest, llvm_tools = true; BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::ToolStd; RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::ToolStd; - RustInstaller, "src/tools/rust-installer", "fabricate", Mode::ToolStd, llvm_tools = false; + RustInstaller, "src/tools/rust-installer", "fabricate", Mode::ToolStd; RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes", Mode::ToolStd; ); diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 9fb7d31ed6f75..8ef45a966da85 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -313,7 +313,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { debug!("consume_body(body={:?})", body); for arg in &body.arguments { - let arg_ty = return_if_err!(self.mc.node_ty(arg.pat.hir_id)); + let arg_ty = return_if_err!(self.mc.pat_ty_adjusted(&arg.pat)); + debug!("consume_body: arg_ty = {:?}", arg_ty); let fn_body_scope_r = self.tcx().mk_region(ty::ReScope(region::Scope::Node(body.value.hir_id.local_id))); diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 959dda69e30ed..597872ef45de0 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -517,7 +517,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { /// implicit deref patterns attached (e.g., it is really /// `&Some(x)`). In that case, we return the "outermost" type /// (e.g., `&Option). - fn pat_ty(&self, pat: &hir::Pat) -> McResult> { + pub fn pat_ty_adjusted(&self, pat: &hir::Pat) -> McResult> { // Check for implicit `&` types wrapping the pattern; note // that these are never attached to binding patterns, so // actually this is somewhat "disjoint" from the code below @@ -1300,7 +1300,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { }; for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) { - let subpat_ty = self.pat_ty(&subpat)?; // see (*2) + let subpat_ty = self.pat_ty_adjusted(&subpat)?; // see (*2) let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string()))); let subcmt = Rc::new(self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior)); self.cat_pattern_(subcmt, &subpat, op)?; @@ -1323,7 +1323,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { }; for fp in field_pats { - let field_ty = self.pat_ty(&fp.node.pat)?; // see (*2) + let field_ty = self.pat_ty_adjusted(&fp.node.pat)?; // see (*2) let f_index = self.tcx.field_index(fp.node.id, self.tables); let cmt_field = Rc::new(self.cat_field(pat, cmt.clone(), f_index, fp.node.ident, field_ty)); @@ -1342,7 +1342,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty), }; for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) { - let subpat_ty = self.pat_ty(&subpat)?; // see (*2) + let subpat_ty = self.pat_ty_unadjusted(&subpat)?; // see (*2) let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string()))); let subcmt = Rc::new(self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior)); self.cat_pattern_(subcmt, &subpat, op)?; diff --git a/src/librustc_allocator/Cargo.toml b/src/librustc_allocator/Cargo.toml index 765cb80f35710..1cbde181cafae 100644 --- a/src/librustc_allocator/Cargo.toml +++ b/src/librustc_allocator/Cargo.toml @@ -14,3 +14,4 @@ rustc_errors = { path = "../librustc_errors" } rustc_target = { path = "../librustc_target" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } +log = "0.4" diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs index ec0676259ef20..3ef99c53705c5 100644 --- a/src/librustc_allocator/expand.rs +++ b/src/librustc_allocator/expand.rs @@ -11,23 +11,28 @@ use rustc::middle::allocator::AllocatorKind; use rustc_errors; use rustc_target::spec::abi::Abi; -use syntax::ast::{Attribute, Crate, LitKind, StrStyle}; -use syntax::ast::{Arg, Constness, Generics, Mac, Mutability, Ty, Unsafety}; -use syntax::ast::{self, Expr, Ident, Item, ItemKind, TyKind, VisibilityKind}; -use syntax::attr; -use syntax::codemap::{dummy_spanned, respan}; -use syntax::codemap::{ExpnInfo, MacroAttribute, NameAndSpan}; -use syntax::ext::base::ExtCtxt; -use syntax::ext::base::Resolver; -use syntax::ext::build::AstBuilder; -use syntax::ext::expand::ExpansionConfig; -use syntax::ext::hygiene::{self, Mark, SyntaxContext}; -use syntax::fold::{self, Folder}; -use syntax::parse::ParseSess; -use syntax::ptr::P; -use syntax::symbol::Symbol; -use syntax::util::small_vector::SmallVector; -use syntax_pos::{Span, DUMMY_SP}; +use syntax::{ + ast::{ + self, Arg, Attribute, Constness, Crate, Expr, Generics, Ident, Item, ItemKind, + LitKind, Mac, Mod, Mutability, StrStyle, Ty, TyKind, Unsafety, VisibilityKind, + }, + attr, + codemap::{ + dummy_spanned, respan, ExpnInfo, MacroAttribute, NameAndSpan, + }, + ext::{ + base::{ExtCtxt, Resolver}, + build::AstBuilder, + expand::ExpansionConfig, + hygiene::{self, Mark, SyntaxContext}, + }, + fold::{self, Folder}, + parse::ParseSess, + ptr::P, + symbol::Symbol, + util::small_vector::SmallVector, +}; +use syntax_pos::Span; use {AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS}; @@ -35,6 +40,7 @@ pub fn modify( sess: &ParseSess, resolver: &mut Resolver, krate: Crate, + crate_name: String, handler: &rustc_errors::Handler, ) -> ast::Crate { ExpandAllocatorDirectives { @@ -42,6 +48,8 @@ pub fn modify( sess, resolver, found: false, + crate_name: Some(crate_name), + in_submod: -1, // -1 to account for the "root" module }.fold_crate(krate) } @@ -50,10 +58,17 @@ struct ExpandAllocatorDirectives<'a> { handler: &'a rustc_errors::Handler, sess: &'a ParseSess, resolver: &'a mut Resolver, + crate_name: Option, + + // For now, we disallow `global_allocator` in submodules because hygiene is hard. Keep track of + // whether we are in a submodule or not. If `in_submod > 0` we are in a submodule. + in_submod: isize, } impl<'a> Folder for ExpandAllocatorDirectives<'a> { fn fold_item(&mut self, item: P) -> SmallVector> { + debug!("in submodule {}", self.in_submod); + let name = if attr::contains_name(&item.attrs, "global_allocator") { "global_allocator" } else { @@ -68,19 +83,23 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> { } } + if self.in_submod > 0 { + self.handler + .span_err(item.span, "`global_allocator` cannot be used in submodules"); + return SmallVector::one(item); + } + if self.found { - self.handler.span_err( - item.span, - "cannot define more than one \ - #[global_allocator]", - ); + self.handler + .span_err(item.span, "cannot define more than one #[global_allocator]"); return SmallVector::one(item); } self.found = true; + // Create a fresh Mark for the new macro expansion we are about to do let mark = Mark::fresh(Mark::root()); mark.set_expn_info(ExpnInfo { - call_site: DUMMY_SP, + call_site: item.span, // use the call site of the static callee: NameAndSpan { format: MacroAttribute(Symbol::intern(name)), span: None, @@ -89,8 +108,14 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> { edition: hygiene::default_edition(), }, }); + + // Tie the span to the macro expansion info we just created let span = item.span.with_ctxt(SyntaxContext::empty().apply_mark(mark)); - let ecfg = ExpansionConfig::default(name.to_string()); + + // Create an expansion config + let ecfg = ExpansionConfig::default(self.crate_name.take().unwrap()); + + // Generate a bunch of new items using the AllocFnFactory let mut f = AllocFnFactory { span, kind: AllocatorKind::Global, @@ -98,29 +123,55 @@ impl<'a> Folder for ExpandAllocatorDirectives<'a> { core: Ident::from_str("core"), cx: ExtCtxt::new(self.sess, ecfg, self.resolver), }; + + // We will generate a new submodule. To `use` the static from that module, we need to get + // the `super::...` path. let super_path = f.cx.path(f.span, vec![Ident::from_str("super"), f.global]); + + // Generate the items in the submodule let mut items = vec![ + // import `core` to use allocators f.cx.item_extern_crate(f.span, f.core), + // `use` the `global_allocator` in `super` f.cx.item_use_simple( f.span, respan(f.span.shrink_to_lo(), VisibilityKind::Inherited), super_path, ), ]; - for method in ALLOCATOR_METHODS { - items.push(f.allocator_fn(method)); - } + + // Add the allocator methods to the submodule + items.extend( + ALLOCATOR_METHODS + .iter() + .map(|method| f.allocator_fn(method)), + ); + + // Generate the submodule itself let name = f.kind.fn_name("allocator_abi"); let allocator_abi = Ident::with_empty_ctxt(Symbol::gensym(&name)); let module = f.cx.item_mod(span, span, allocator_abi, Vec::new(), items); let module = f.cx.monotonic_expander().fold_item(module).pop().unwrap(); - let mut ret = SmallVector::new(); + // Return the item and new submodule + let mut ret = SmallVector::with_capacity(2); ret.push(item); ret.push(module); + return ret; } + // If we enter a submodule, take note. + fn fold_mod(&mut self, m: Mod) -> Mod { + debug!("enter submodule"); + self.in_submod += 1; + let ret = fold::noop_fold_mod(m, self); + self.in_submod -= 1; + debug!("exit submodule"); + ret + } + + // `fold_mac` is disabled by default. Enable it here. fn fold_mac(&mut self, mac: Mac) -> Mac { fold::noop_fold_mac(mac, self) } diff --git a/src/librustc_allocator/lib.rs b/src/librustc_allocator/lib.rs index 6595564fb30b5..b217d3665a245 100644 --- a/src/librustc_allocator/lib.rs +++ b/src/librustc_allocator/lib.rs @@ -10,6 +10,7 @@ #![feature(rustc_private)] +#[macro_use] extern crate log; extern crate rustc; extern crate rustc_errors; extern crate rustc_target; diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index c18a089268659..feeac9d938b6a 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -1051,10 +1051,19 @@ where }); } + // Expand global allocators, which are treated as an in-tree proc macro krate = time(sess, "creating allocators", || { - allocator::expand::modify(&sess.parse_sess, &mut resolver, krate, sess.diagnostic()) + allocator::expand::modify( + &sess.parse_sess, + &mut resolver, + krate, + crate_name.to_string(), + sess.diagnostic(), + ) }); + // Done with macro expansion! + after_expand(&krate)?; if sess.opts.debugging_opts.input_stats { diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index 3fcf1b5c8ed59..592c9dbe6ffe4 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -76,7 +76,7 @@ pub fn value_to_const_value<'tcx>( val: Value, ty: Ty<'tcx>, ) -> &'tcx ty::Const<'tcx> { - let layout = ecx.tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap(); + let layout = ecx.layout_of(ty).unwrap(); match (val, &layout.abi) { (Value::Scalar(Scalar::Bits { defined: 0, ..}), _) if layout.is_zst() => {}, (Value::ByRef(..), _) | diff --git a/src/test/ui/allocator-submodule.rs b/src/test/ui/allocator-submodule.rs new file mode 100644 index 0000000000000..39b65766924f9 --- /dev/null +++ b/src/test/ui/allocator-submodule.rs @@ -0,0 +1,40 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Tests that it is possible to create a global allocator in a submodule, rather than in the crate +// root. + +#![feature(alloc, allocator_api, global_allocator)] + +extern crate alloc; + +use std::{ + alloc::{GlobalAlloc, Layout}, + ptr, +}; + +struct MyAlloc; + +unsafe impl GlobalAlloc for MyAlloc { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + ptr::null_mut() + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {} +} + +mod submod { + use super::MyAlloc; + + #[global_allocator] + static MY_HEAP: MyAlloc = MyAlloc; //~ ERROR global_allocator +} + +fn main() {} diff --git a/src/test/ui/allocator-submodule.stderr b/src/test/ui/allocator-submodule.stderr new file mode 100644 index 0000000000000..06e0d36e8a2b1 --- /dev/null +++ b/src/test/ui/allocator-submodule.stderr @@ -0,0 +1,8 @@ +error: `global_allocator` cannot be used in submodules + --> $DIR/allocator-submodule.rs:37:5 + | +LL | static MY_HEAP: MyAlloc = MyAlloc; //~ ERROR global_allocator + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/borrowck/issue-51415.nll.stderr b/src/test/ui/borrowck/issue-51415.nll.stderr new file mode 100644 index 0000000000000..79454b635263c --- /dev/null +++ b/src/test/ui/borrowck/issue-51415.nll.stderr @@ -0,0 +1,9 @@ +error[E0507]: cannot move out of borrowed content + --> $DIR/issue-51415.rs:16:47 + | +LL | let opt = a.iter().enumerate().find(|(_, &s)| { + | ^ cannot move out of borrowed content + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/borrowck/issue-51415.rs b/src/test/ui/borrowck/issue-51415.rs new file mode 100644 index 0000000000000..9067a50a8476d --- /dev/null +++ b/src/test/ui/borrowck/issue-51415.rs @@ -0,0 +1,21 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #51415: match default bindings were failing to +// see the "move out" implied by `&s` below. + +fn main() { + let a = vec![String::from("a")]; + let opt = a.iter().enumerate().find(|(_, &s)| { + //~^ ERROR cannot move out + *s == String::from("d") + }).map(|(i, _)| i); + println!("{:?}", opt); +} diff --git a/src/test/ui/borrowck/issue-51415.stderr b/src/test/ui/borrowck/issue-51415.stderr new file mode 100644 index 0000000000000..b4b0bc7594305 --- /dev/null +++ b/src/test/ui/borrowck/issue-51415.stderr @@ -0,0 +1,12 @@ +error[E0507]: cannot move out of borrowed content + --> $DIR/issue-51415.rs:16:46 + | +LL | let opt = a.iter().enumerate().find(|(_, &s)| { + | ^- + | || + | |hint: to prevent move, use `ref s` or `ref mut s` + | cannot move out of borrowed content + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. diff --git a/src/test/ui/const-eval/ice-generic-assoc-const.rs b/src/test/ui/const-eval/ice-generic-assoc-const.rs new file mode 100644 index 0000000000000..31e056b66bce9 --- /dev/null +++ b/src/test/ui/const-eval/ice-generic-assoc-const.rs @@ -0,0 +1,28 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass + +pub trait Nullable { + const NULL: Self; + + fn is_null(&self) -> bool; +} + +impl Nullable for *const T { + const NULL: Self = 0 as *const T; + + fn is_null(&self) -> bool { + *self == Self::NULL + } +} + +fn main() { +}