Skip to content

Commit

Permalink
Auto merge of rust-lang#81355 - jonas-schievink:rollup-vpaadij, r=jon…
Browse files Browse the repository at this point in the history
…as-schievink

Rollup of 14 pull requests

Successful merges:

 - rust-lang#75180 (Implement Error for &(impl Error))
 - rust-lang#78578 (Permit mutable references in all const contexts)
 - rust-lang#79174 (Make std::future a re-export of core::future)
 - rust-lang#79884 (Replace magic numbers with existing constants)
 - rust-lang#80855 (Expand assert!(expr, args..) to include $crate for hygiene on 2021.)
 - rust-lang#80933 (Fix sysroot option not being honored across rustc)
 - rust-lang#81259 (Replace version_check dependency with own version parsing code)
 - rust-lang#81264 (Add unstable option to control doctest run directory)
 - rust-lang#81279 (Small refactor in typeck)
 - rust-lang#81297 (Don't provide backend_optimization_level query for extern crates)
 - rust-lang#81302 (Fix rendering of stabilization version for trait implementors)
 - rust-lang#81310 (Do not mark unit variants as used when in path pattern)
 - rust-lang#81320 (Make bad shlex parsing a pretty error)
 - rust-lang#81338 (Clean up `dominators_given_rpo`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Jan 24, 2021
2 parents 1d0d76f + 529f15f commit d3163e9
Show file tree
Hide file tree
Showing 67 changed files with 942 additions and 441 deletions.
1 change: 0 additions & 1 deletion Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3568,7 +3568,6 @@ dependencies = [
"rustc_serialize",
"rustc_session",
"rustc_span",
"version_check",
]

[[package]]
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_attr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,3 @@ rustc_lexer = { path = "../rustc_lexer" }
rustc_macros = { path = "../rustc_macros" }
rustc_session = { path = "../rustc_session" }
rustc_ast = { path = "../rustc_ast" }
version_check = "0.9"
32 changes: 28 additions & 4 deletions compiler/rustc_attr/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use rustc_session::Session;
use rustc_span::hygiene::Transparency;
use rustc_span::{symbol::sym, symbol::Symbol, Span};
use std::num::NonZeroU32;
use version_check::Version;

pub fn is_builtin_attr(attr: &Attribute) -> bool {
attr.is_doc_comment() || attr.ident().filter(|ident| is_builtin_attr_name(ident.name)).is_some()
Expand Down Expand Up @@ -526,6 +525,26 @@ fn gate_cfg(gated_cfg: &GatedCfg, cfg_span: Span, sess: &ParseSess, features: &F
}
}

#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
struct Version {
major: u16,
minor: u16,
patch: u16,
}

fn parse_version(s: &str, allow_appendix: bool) -> Option<Version> {
let mut components = s.split('-');
let d = components.next()?;
if !allow_appendix && components.next().is_some() {
return None;
}
let mut digits = d.splitn(3, '.');
let major = digits.next()?.parse().ok()?;
let minor = digits.next()?.parse().ok()?;
let patch = digits.next().unwrap_or("0").parse().ok()?;
Some(Version { major, minor, patch })
}

/// Evaluate a cfg-like condition (with `any` and `all`), using `eval` to
/// evaluate individual items.
pub fn eval_condition(
Expand Down Expand Up @@ -555,16 +574,21 @@ pub fn eval_condition(
return false;
}
};
let min_version = match Version::parse(&min_version.as_str()) {
let min_version = match parse_version(&min_version.as_str(), false) {
Some(ver) => ver,
None => {
sess.span_diagnostic.struct_span_err(*span, "invalid version literal").emit();
sess.span_diagnostic
.struct_span_warn(
*span,
"unknown version literal format, assuming it refers to a future version",
)
.emit();
return false;
}
};
let channel = env!("CFG_RELEASE_CHANNEL");
let nightly = channel == "nightly" || channel == "dev";
let rustc_version = Version::parse(env!("CFG_RELEASE")).unwrap();
let rustc_version = parse_version(env!("CFG_RELEASE"), true).unwrap();

// See https://github.com/rust-lang/rust/issues/64796#issuecomment-625474439 for details
if nightly { rustc_version > min_version } else { rustc_version >= min_version }
Expand Down
26 changes: 21 additions & 5 deletions compiler/rustc_builtin_macros/src/assert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,43 @@ use rustc_span::{Span, DUMMY_SP};

pub fn expand_assert<'cx>(
cx: &'cx mut ExtCtxt<'_>,
sp: Span,
span: Span,
tts: TokenStream,
) -> Box<dyn MacResult + 'cx> {
let Assert { cond_expr, custom_message } = match parse_assert(cx, sp, tts) {
let Assert { cond_expr, custom_message } = match parse_assert(cx, span, tts) {
Ok(assert) => assert,
Err(mut err) => {
err.emit();
return DummyResult::any(sp);
return DummyResult::any(span);
}
};

// `core::panic` and `std::panic` are different macros, so we use call-site
// context to pick up whichever is currently in scope.
let sp = cx.with_call_site_ctxt(sp);
let sp = cx.with_call_site_ctxt(span);

let panic_call = if let Some(tokens) = custom_message {
let path = if span.rust_2021() {
// On edition 2021, we always call `$crate::panic!()`.
Path {
span: sp,
segments: cx
.std_path(&[sym::panic])
.into_iter()
.map(|ident| PathSegment::from_ident(ident))
.collect(),
tokens: None,
}
} else {
// Before edition 2021, we call `panic!()` unqualified,
// such that it calls either `std::panic!()` or `core::panic!()`.
Path::from_ident(Ident::new(sym::panic, sp))
};
// Pass the custom message to panic!().
cx.expr(
sp,
ExprKind::MacCall(MacCall {
path: Path::from_ident(Ident::new(sym::panic, sp)),
path,
args: P(MacArgs::Delimited(
DelimSpan::from_single(sp),
MacDelimiter::Parenthesis,
Expand Down
28 changes: 21 additions & 7 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -885,9 +885,22 @@ fn link_sanitizers(sess: &Session, crate_type: CrateType, linker: &mut dyn Linke
}

fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) {
let default_sysroot = filesearch::get_or_default_sysroot();
let default_tlib =
filesearch::make_target_lib_path(&default_sysroot, sess.opts.target_triple.triple());
fn find_sanitizer_runtime(sess: &Session, filename: &String) -> PathBuf {
let session_tlib =
filesearch::make_target_lib_path(&sess.sysroot, sess.opts.target_triple.triple());
let path = session_tlib.join(&filename);
if path.exists() {
return session_tlib;
} else {
let default_sysroot = filesearch::get_or_default_sysroot();
let default_tlib = filesearch::make_target_lib_path(
&default_sysroot,
sess.opts.target_triple.triple(),
);
return default_tlib;
}
}

let channel = option_env!("CFG_RELEASE_CHANNEL")
.map(|channel| format!("-{}", channel))
.unwrap_or_default();
Expand All @@ -898,18 +911,19 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) {
// LLVM will link to `@rpath/*.dylib`, so we need to specify an
// rpath to the library as well (the rpath should be absolute, see
// PR #41352 for details).
let libname = format!("rustc{}_rt.{}", channel, name);
let rpath = default_tlib.to_str().expect("non-utf8 component in path");
let filename = format!("rustc{}_rt.{}", channel, name);
let path = find_sanitizer_runtime(&sess, &filename);
let rpath = path.to_str().expect("non-utf8 component in path");
linker.args(&["-Wl,-rpath", "-Xlinker", rpath]);
linker.link_dylib(Symbol::intern(&libname));
linker.link_dylib(Symbol::intern(&filename));
}
"aarch64-fuchsia"
| "aarch64-unknown-linux-gnu"
| "x86_64-fuchsia"
| "x86_64-unknown-freebsd"
| "x86_64-unknown-linux-gnu" => {
let filename = format!("librustc{}_rt.{}.a", channel, name);
let path = default_tlib.join(&filename);
let path = find_sanitizer_runtime(&sess, &filename).join(&filename);
linker.link_whole_rlib(&path);
}
_ => {}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_ssa/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,7 @@ impl CrateInfo {
}
}

pub fn provide_both(providers: &mut Providers) {
pub fn provide(providers: &mut Providers) {
providers.backend_optimization_level = |tcx, cratenum| {
let for_speed = match tcx.sess.opts.optimize {
// If globally no optimisation is done, #[optimize] has no effect.
Expand Down
3 changes: 1 addition & 2 deletions compiler/rustc_codegen_ssa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,12 @@ pub struct CodegenResults {

pub fn provide(providers: &mut Providers) {
crate::back::symbol_export::provide(providers);
crate::base::provide_both(providers);
crate::base::provide(providers);
crate::target_features::provide(providers);
}

pub fn provide_extern(providers: &mut Providers) {
crate::back::symbol_export::provide_extern(providers);
crate::base::provide_both(providers);
}

/// Checks if the given filename ends with the `.rcgu.o` extension that `rustc`
Expand Down
16 changes: 5 additions & 11 deletions compiler/rustc_data_structures/src/graph/dominators/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use super::iterate::reverse_post_order;
use super::ControlFlowGraph;
use rustc_index::vec::{Idx, IndexVec};
use std::borrow::BorrowMut;
use std::cmp::Ordering;

#[cfg(test)]
Expand All @@ -20,22 +19,17 @@ pub fn dominators<G: ControlFlowGraph>(graph: G) -> Dominators<G::Node> {
dominators_given_rpo(graph, &rpo)
}

fn dominators_given_rpo<G: ControlFlowGraph + BorrowMut<G>>(
mut graph: G,
rpo: &[G::Node],
) -> Dominators<G::Node> {
let start_node = graph.borrow().start_node();
fn dominators_given_rpo<G: ControlFlowGraph>(graph: G, rpo: &[G::Node]) -> Dominators<G::Node> {
let start_node = graph.start_node();
assert_eq!(rpo[0], start_node);

// compute the post order index (rank) for each node
let mut post_order_rank: IndexVec<G::Node, usize> =
(0..graph.borrow().num_nodes()).map(|_| 0).collect();
let mut post_order_rank = IndexVec::from_elem_n(0, graph.num_nodes());
for (index, node) in rpo.iter().rev().cloned().enumerate() {
post_order_rank[node] = index;
}

let mut immediate_dominators: IndexVec<G::Node, Option<G::Node>> =
(0..graph.borrow().num_nodes()).map(|_| None).collect();
let mut immediate_dominators = IndexVec::from_elem_n(None, graph.num_nodes());
immediate_dominators[start_node] = Some(start_node);

let mut changed = true;
Expand All @@ -44,7 +38,7 @@ fn dominators_given_rpo<G: ControlFlowGraph + BorrowMut<G>>(

for &node in &rpo[1..] {
let mut new_idom = None;
for pred in graph.borrow_mut().predecessors(node) {
for pred in graph.predecessors(node) {
if immediate_dominators[pred].is_some() {
// (*) dominators for `pred` have been calculated
new_idom = Some(if let Some(new_idom) = new_idom {
Expand Down
71 changes: 44 additions & 27 deletions compiler/rustc_mir/src/transform/check_consts/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,16 +268,20 @@ impl NonConstOp for CellBorrow {
}

#[derive(Debug)]
/// This op is for `&mut` borrows in the trailing expression of a constant
/// which uses the "enclosing scopes rule" to leak its locals into anonymous
/// static or const items.
pub struct MutBorrow(pub hir::BorrowKind);

impl NonConstOp for MutBorrow {
fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
// Forbid everywhere except in const fn with a feature gate
if ccx.const_kind() == hir::ConstContext::ConstFn {
Status::Unstable(sym::const_mut_refs)
} else {
Status::Forbidden
}
fn status_in_item(&self, _ccx: &ConstCx<'_, '_>) -> Status {
Status::Forbidden
}

fn importance(&self) -> DiagnosticImportance {
// If there were primary errors (like non-const function calls), do not emit further
// errors about mutable references.
DiagnosticImportance::Secondary
}

fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
Expand All @@ -286,25 +290,15 @@ impl NonConstOp for MutBorrow {
hir::BorrowKind::Ref => "",
};

let mut err = if ccx.const_kind() == hir::ConstContext::ConstFn {
feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_mut_refs,
span,
&format!("{}mutable references are not allowed in {}s", raw, ccx.const_kind()),
)
} else {
let mut err = struct_span_err!(
ccx.tcx.sess,
span,
E0764,
"{}mutable references are not allowed in {}s",
raw,
ccx.const_kind(),
);
err.span_label(span, format!("`&{}mut` is only allowed in `const fn`", raw));
err
};
let mut err = struct_span_err!(
ccx.tcx.sess,
span,
E0764,
"{}mutable references are not allowed in the final value of {}s",
raw,
ccx.const_kind(),
);

if ccx.tcx.sess.teach(&err.get_code().unwrap()) {
err.note(
"References in statics and constants may only refer \
Expand All @@ -321,6 +315,29 @@ impl NonConstOp for MutBorrow {
}
}

#[derive(Debug)]
pub struct TransientMutBorrow(pub hir::BorrowKind);

impl NonConstOp for TransientMutBorrow {
fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
Status::Unstable(sym::const_mut_refs)
}

fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
let raw = match self.0 {
hir::BorrowKind::Raw => "raw ",
hir::BorrowKind::Ref => "",
};

feature_err(
&ccx.tcx.sess.parse_sess,
sym::const_mut_refs,
span,
&format!("{}mutable references are not allowed in {}s", raw, ccx.const_kind()),
)
}
}

#[derive(Debug)]
pub struct MutDeref;
impl NonConstOp for MutDeref {
Expand All @@ -329,7 +346,7 @@ impl NonConstOp for MutDeref {
}

fn importance(&self) -> DiagnosticImportance {
// Usually a side-effect of a `MutBorrow` somewhere.
// Usually a side-effect of a `TransientMutBorrow` somewhere.
DiagnosticImportance::Secondary
}

Expand Down
29 changes: 26 additions & 3 deletions compiler/rustc_mir/src/transform/check_consts/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,29 @@ impl Validator<'mir, 'tcx> {
}
}
}

fn check_mut_borrow(&mut self, local: Local, kind: hir::BorrowKind) {
match self.const_kind() {
// In a const fn all borrows are transient or point to the places given via
// references in the arguments (so we already checked them with
// TransientMutBorrow/MutBorrow as appropriate).
// The borrow checker guarantees that no new non-transient borrows are created.
// NOTE: Once we have heap allocations during CTFE we need to figure out
// how to prevent `const fn` to create long-lived allocations that point
// to mutable memory.
hir::ConstContext::ConstFn => self.check_op(ops::TransientMutBorrow(kind)),
_ => {
// Locals with StorageDead do not live beyond the evaluation and can
// thus safely be borrowed without being able to be leaked to the final
// value of the constant.
if self.local_has_storage_dead(local) {
self.check_op(ops::TransientMutBorrow(kind));
} else {
self.check_op(ops::MutBorrow(kind));
}
}
}
}
}

impl Visitor<'tcx> for Validator<'mir, 'tcx> {
Expand Down Expand Up @@ -562,15 +585,15 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> {

if !is_allowed {
if let BorrowKind::Mut { .. } = kind {
self.check_op(ops::MutBorrow(hir::BorrowKind::Ref));
self.check_mut_borrow(place.local, hir::BorrowKind::Ref)
} else {
self.check_op(ops::CellBorrow);
}
}
}

Rvalue::AddressOf(Mutability::Mut, _) => {
self.check_op(ops::MutBorrow(hir::BorrowKind::Raw))
Rvalue::AddressOf(Mutability::Mut, ref place) => {
self.check_mut_borrow(place.local, hir::BorrowKind::Raw)
}

Rvalue::Ref(_, BorrowKind::Shared | BorrowKind::Shallow, ref place)
Expand Down
Loading

0 comments on commit d3163e9

Please sign in to comment.