Skip to content

Rollup of 6 pull requests #89435

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
Oct 1, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions Cargo.lock
Original file line number Diff line number Diff line change
@@ -1660,7 +1660,7 @@ checksum = "3ca8957e71f04a205cb162508f9326aea04676c8dfd0711220190d6b83664f3f"
dependencies = [
"bitmaps",
"rand_core 0.5.1",
"rand_xoshiro",
"rand_xoshiro 0.4.0",
"sized-chunks",
"typenum",
"version_check",
@@ -2256,7 +2256,7 @@ dependencies = [
"libc",
"log",
"measureme",
"rand 0.8.3",
"rand 0.8.4",
"rustc-workspace-hack",
"rustc_version",
"shell-escape",
@@ -2852,9 +2852,9 @@ dependencies = [

[[package]]
name = "rand"
version = "0.8.3"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
dependencies = [
"libc",
"rand_chacha 0.3.0",
@@ -2945,6 +2945,15 @@ dependencies = [
"rand_core 0.5.1",
]

[[package]]
name = "rand_xoshiro"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa"
dependencies = [
"rand_core 0.6.2",
]

[[package]]
name = "rayon"
version = "1.3.1"
@@ -4087,6 +4096,8 @@ dependencies = [
"either",
"gsgdt",
"polonius-engine",
"rand 0.8.4",
"rand_xoshiro 0.6.0",
"rustc-rayon-core",
"rustc_apfloat",
"rustc_arena",
@@ -5097,7 +5108,7 @@ checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
dependencies = [
"cfg-if 1.0.0",
"libc",
"rand 0.8.3",
"rand 0.8.4",
"redox_syscall",
"remove_dir_all",
"winapi",
26 changes: 21 additions & 5 deletions compiler/rustc_builtin_macros/src/format.rs
Original file line number Diff line number Diff line change
@@ -1154,11 +1154,12 @@ pub fn expand_preparsed_format_args(
// account for `"` and account for raw strings `r#`
let padding = str_style.map(|i| i + 2).unwrap_or(1);
for sub in foreign::$kind::iter_subs(fmt_str, padding) {
let trn = match sub.translate() {
Some(trn) => trn,
let (trn, success) = match sub.translate() {
Ok(trn) => (trn, true),
Err(Some(msg)) => (msg, false),

// If it has no translation, don't call it out specifically.
None => continue,
_ => continue,
};

let pos = sub.position();
@@ -1175,9 +1176,24 @@ pub fn expand_preparsed_format_args(

if let Some(inner_sp) = pos {
let sp = fmt_sp.from_inner(inner_sp);
suggestions.push((sp, trn));

if success {
suggestions.push((sp, trn));
} else {
diag.span_note(
sp,
&format!("format specifiers use curly braces, and {}", trn),
);
}
} else {
diag.help(&format!("`{}` should be written as `{}`", sub, trn));
if success {
diag.help(&format!("`{}` should be written as `{}`", sub, trn));
} else {
diag.note(&format!(
"`{}` should use curly braces, and {}",
sub, trn
));
}
}
}

65 changes: 48 additions & 17 deletions compiler/rustc_builtin_macros/src/format_foreign.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub mod printf {
pub(crate) mod printf {
use super::strcursor::StrCursor as Cur;
use rustc_span::InnerSpan;

@@ -36,10 +36,10 @@ pub mod printf {
///
/// This ignores cases where the substitution does not have an exact equivalent, or where
/// the substitution would be unnecessary.
pub fn translate(&self) -> Option<String> {
pub fn translate(&self) -> Result<String, Option<String>> {
match *self {
Substitution::Format(ref fmt) => fmt.translate(),
Substitution::Escape => None,
Substitution::Escape => Err(None),
}
}
}
@@ -68,9 +68,9 @@ pub mod printf {
impl Format<'_> {
/// Translate this directive into an equivalent Rust formatting directive.
///
/// Returns `None` in cases where the `printf` directive does not have an exact Rust
/// Returns `Err` in cases where the `printf` directive does not have an exact Rust
/// equivalent, rather than guessing.
pub fn translate(&self) -> Option<String> {
pub fn translate(&self) -> Result<String, Option<String>> {
use std::fmt::Write;

let (c_alt, c_zero, c_left, c_plus) = {
@@ -84,7 +84,12 @@ pub mod printf {
'0' => c_zero = true,
'-' => c_left = true,
'+' => c_plus = true,
_ => return None,
_ => {
return Err(Some(format!(
"the flag `{}` is unknown or unsupported",
c
)));
}
}
}
(c_alt, c_zero, c_left, c_plus)
@@ -104,7 +109,9 @@ pub mod printf {
let width = match self.width {
Some(Num::Next) => {
// NOTE: Rust doesn't support this.
return None;
return Err(Some(
"you have to use a positional or named parameter for the width".to_string(),
));
}
w @ Some(Num::Arg(_)) => w,
w @ Some(Num::Num(_)) => w,
@@ -125,13 +132,21 @@ pub mod printf {
"p" => (Some(self.type_), false, true),
"g" => (Some("e"), true, false),
"G" => (Some("E"), true, false),
_ => return None,
_ => {
return Err(Some(format!(
"the conversion specifier `{}` is unknown or unsupported",
self.type_
)));
}
};

let (fill, width, precision) = match (is_int, width, precision) {
(true, Some(_), Some(_)) => {
// Rust can't duplicate this insanity.
return None;
return Err(Some(
"width and precision cannot both be specified for integer conversions"
.to_string(),
));
}
(true, None, Some(p)) => (Some("0"), Some(p), None),
(true, w, None) => (fill, w, None),
@@ -169,7 +184,17 @@ pub mod printf {
s.push('{');

if let Some(arg) = self.parameter {
write!(s, "{}", arg.checked_sub(1)?).ok()?;
match write!(
s,
"{}",
match arg.checked_sub(1) {
Some(a) => a,
None => return Err(None),
}
) {
Err(_) => return Err(None),
_ => {}
}
}

if has_options {
@@ -199,12 +224,18 @@ pub mod printf {
}

if let Some(width) = width {
width.translate(&mut s).ok()?;
match width.translate(&mut s) {
Err(_) => return Err(None),
_ => {}
}
}

if let Some(precision) = precision {
s.push('.');
precision.translate(&mut s).ok()?;
match precision.translate(&mut s) {
Err(_) => return Err(None),
_ => {}
}
}

if let Some(type_) = type_ {
@@ -213,7 +244,7 @@ pub mod printf {
}

s.push('}');
Some(s)
Ok(s)
}
}

@@ -623,11 +654,11 @@ pub mod shell {
}
}

pub fn translate(&self) -> Option<String> {
pub fn translate(&self) -> Result<String, Option<String>> {
match *self {
Substitution::Ordinal(n, _) => Some(format!("{{{}}}", n)),
Substitution::Name(n, _) => Some(format!("{{{}}}", n)),
Substitution::Escape(_) => None,
Substitution::Ordinal(n, _) => Ok(format!("{{{}}}", n)),
Substitution::Name(n, _) => Ok(format!("{{{}}}", n)),
Substitution::Escape(_) => Err(None),
}
}
}
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ use super::{iter_subs, parse_next_substitution as pns, Format as F, Num as N, Su
macro_rules! assert_eq_pnsat {
($lhs:expr, $rhs:expr) => {
assert_eq!(
pns($lhs).and_then(|(s, _)| s.translate()),
pns($lhs).and_then(|(s, _)| s.translate().ok()),
$rhs.map(<String as From<&str>>::from)
)
};
@@ -98,7 +98,7 @@ fn test_parse() {
#[test]
fn test_iter() {
let s = "The %d'th word %% is: `%.*s` %!\n";
let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate()).collect();
let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate().ok()).collect();
assert_eq!(
subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::<Vec<_>>(),
vec![Some("{}"), None, Some("{:.*}"), None]
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ use super::{parse_next_substitution as pns, Substitution as S};
macro_rules! assert_eq_pnsat {
($lhs:expr, $rhs:expr) => {
assert_eq!(
pns($lhs).and_then(|(f, _)| f.translate()),
pns($lhs).and_then(|(f, _)| f.translate().ok()),
$rhs.map(<String as From<&str>>::from)
)
};
@@ -37,7 +37,7 @@ fn test_parse() {
fn test_iter() {
use super::iter_subs;
let s = "The $0'th word $$ is: `$WORD` $!\n";
let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate()).collect();
let subs: Vec<_> = iter_subs(s, 0).map(|sub| sub.translate().ok()).collect();
assert_eq!(
subs.iter().map(|ms| ms.as_ref().map(|s| &s[..])).collect::<Vec<_>>(),
vec![Some("{0}"), None, Some("{WORD}")]
3 changes: 2 additions & 1 deletion compiler/rustc_codegen_llvm/src/back/write.rs
Original file line number Diff line number Diff line change
@@ -129,7 +129,8 @@ fn to_pass_builder_opt_level(cfg: config::OptLevel) -> llvm::PassBuilderOptLevel
fn to_llvm_relocation_model(relocation_model: RelocModel) -> llvm::RelocModel {
match relocation_model {
RelocModel::Static => llvm::RelocModel::Static,
RelocModel::Pic => llvm::RelocModel::PIC,
// LLVM doesn't have a PIE relocation model, it represents PIE as PIC with an extra attribute.
RelocModel::Pic | RelocModel::Pie => llvm::RelocModel::PIC,
RelocModel::DynamicNoPic => llvm::RelocModel::DynamicNoPic,
RelocModel::Ropi => llvm::RelocModel::ROPI,
RelocModel::Rwpi => llvm::RelocModel::RWPI,
7 changes: 5 additions & 2 deletions compiler/rustc_codegen_llvm/src/context.rs
Original file line number Diff line number Diff line change
@@ -195,11 +195,14 @@ pub unsafe fn create_module(
let llvm_target = SmallCStr::new(&sess.target.llvm_target);
llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());

if sess.relocation_model() == RelocModel::Pic {
let reloc_model = sess.relocation_model();
if matches!(reloc_model, RelocModel::Pic | RelocModel::Pie) {
llvm::LLVMRustSetModulePICLevel(llmod);
// PIE is potentially more effective than PIC, but can only be used in executables.
// If all our outputs are executables, then we can relax PIC to PIE.
if sess.crate_types().iter().all(|ty| *ty == CrateType::Executable) {
if reloc_model == RelocModel::Pie
|| sess.crate_types().iter().all(|ty| *ty == CrateType::Executable)
{
llvm::LLVMRustSetModulePIELevel(llmod);
}
}
13 changes: 10 additions & 3 deletions compiler/rustc_codegen_llvm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -211,9 +211,16 @@ impl CodegenBackend for LlvmCodegenBackend {
match req {
PrintRequest::RelocationModels => {
println!("Available relocation models:");
for name in
&["static", "pic", "dynamic-no-pic", "ropi", "rwpi", "ropi-rwpi", "default"]
{
for name in &[
"static",
"pic",
"pie",
"dynamic-no-pic",
"ropi",
"rwpi",
"ropi-rwpi",
"default",
] {
println!(" {}", name);
}
println!();
6 changes: 6 additions & 0 deletions compiler/rustc_codegen_llvm/src/mono_item.rs
Original file line number Diff line number Diff line change
@@ -143,6 +143,12 @@ impl CodegenCx<'ll, 'tcx> {
return true;
}

// With pie relocation model calls of functions defined in the translation
// unit can use copy relocations.
if self.tcx.sess.relocation_model() == RelocModel::Pie && !is_declaration {
return true;
}

return false;
}
}
8 changes: 6 additions & 2 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
@@ -1490,9 +1490,13 @@ fn exec_linker(
fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind {
let kind = match (crate_type, sess.crt_static(Some(crate_type)), sess.relocation_model()) {
(CrateType::Executable, _, _) if sess.is_wasi_reactor() => LinkOutputKind::WasiReactorExe,
(CrateType::Executable, false, RelocModel::Pic) => LinkOutputKind::DynamicPicExe,
(CrateType::Executable, false, RelocModel::Pic | RelocModel::Pie) => {
LinkOutputKind::DynamicPicExe
}
(CrateType::Executable, false, _) => LinkOutputKind::DynamicNoPicExe,
(CrateType::Executable, true, RelocModel::Pic) => LinkOutputKind::StaticPicExe,
(CrateType::Executable, true, RelocModel::Pic | RelocModel::Pie) => {
LinkOutputKind::StaticPicExe
}
(CrateType::Executable, true, _) => LinkOutputKind::StaticNoPicExe,
(_, true, _) => LinkOutputKind::StaticDylib,
(_, false, _) => LinkOutputKind::DynamicDylib,
10 changes: 10 additions & 0 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
@@ -384,6 +384,16 @@ impl GenericArgs<'_> {
self.args.iter().any(|arg| matches!(arg, GenericArg::Type(_)))
}

pub fn has_err(&self) -> bool {
self.args.iter().any(|arg| match arg {
GenericArg::Type(ty) => matches!(ty.kind, TyKind::Err),
_ => false,
}) || self.bindings.iter().any(|arg| match arg.kind {
TypeBindingKind::Equality { ty } => matches!(ty.kind, TyKind::Err),
_ => false,
})
}

#[inline]
pub fn num_type_params(&self) -> usize {
self.args.iter().filter(|arg| matches!(arg, GenericArg::Type(_))).count()
2 changes: 2 additions & 0 deletions compiler/rustc_middle/Cargo.toml
Original file line number Diff line number Diff line change
@@ -32,3 +32,5 @@ chalk-ir = "0.55.0"
smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
rustc_session = { path = "../rustc_session" }
rustc_type_ir = { path = "../rustc_type_ir" }
rand = "0.8.4"
rand_xoshiro = "0.6.0"
48 changes: 35 additions & 13 deletions compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
@@ -24,6 +24,9 @@ use std::iter;
use std::num::NonZeroUsize;
use std::ops::Bound;

use rand::{seq::SliceRandom, SeedableRng};
use rand_xoshiro::Xoshiro128StarStar;

pub fn provide(providers: &mut ty::query::Providers) {
*providers =
ty::query::Providers { layout_of, fn_abi_of_fn_ptr, fn_abi_of_instance, ..*providers };
@@ -324,6 +327,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {

let mut inverse_memory_index: Vec<u32> = (0..fields.len() as u32).collect();

// `ReprOptions.layout_seed` is a deterministic seed that we can use to
// randomize field ordering with
let mut rng = Xoshiro128StarStar::seed_from_u64(repr.field_shuffle_seed);

let optimize = !repr.inhibit_struct_field_reordering_opt();
if optimize {
let end =
@@ -332,20 +339,35 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
let field_align = |f: &TyAndLayout<'_>| {
if let Some(pack) = pack { f.align.abi.min(pack) } else { f.align.abi }
};
match kind {
StructKind::AlwaysSized | StructKind::MaybeUnsized => {
optimizing.sort_by_key(|&x| {
// Place ZSTs first to avoid "interesting offsets",
// especially with only one or two non-ZST fields.
let f = &fields[x as usize];
(!f.is_zst(), cmp::Reverse(field_align(f)))
});
}
StructKind::Prefixed(..) => {
// Sort in ascending alignment so that the layout stay optimal
// regardless of the prefix
optimizing.sort_by_key(|&x| field_align(&fields[x as usize]));

// If `-Z randomize-layout` was enabled for the type definition we can shuffle
// the field ordering to try and catch some code making assumptions about layouts
// we don't guarantee
if repr.can_randomize_type_layout() {
// Shuffle the ordering of the fields
optimizing.shuffle(&mut rng);

// Otherwise we just leave things alone and actually optimize the type's fields
} else {
match kind {
StructKind::AlwaysSized | StructKind::MaybeUnsized => {
optimizing.sort_by_key(|&x| {
// Place ZSTs first to avoid "interesting offsets",
// especially with only one or two non-ZST fields.
let f = &fields[x as usize];
(!f.is_zst(), cmp::Reverse(field_align(f)))
});
}

StructKind::Prefixed(..) => {
// Sort in ascending alignment so that the layout stays optimal
// regardless of the prefix
optimizing.sort_by_key(|&x| field_align(&fields[x as usize]));
}
}

// FIXME(Kixiron): We can always shuffle fields within a given alignment class
// regardless of the status of `-Z randomize-layout`
}
}

38 changes: 37 additions & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
@@ -1491,6 +1491,9 @@ bitflags! {
const IS_LINEAR = 1 << 3;
// If true, don't expose any niche to type's context.
const HIDE_NICHE = 1 << 4;
// If true, the type's layout can be randomized using
// the seed stored in `ReprOptions.layout_seed`
const RANDOMIZE_LAYOUT = 1 << 5;
// Any of these flags being set prevent field reordering optimisation.
const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits |
ReprFlags::IS_SIMD.bits |
@@ -1505,6 +1508,14 @@ pub struct ReprOptions {
pub align: Option<Align>,
pub pack: Option<Align>,
pub flags: ReprFlags,
/// The seed to be used for randomizing a type's layout
///
/// Note: This could technically be a `[u8; 16]` (a `u128`) which would
/// be the "most accurate" hash as it'd encompass the item and crate
/// hash without loss, but it does pay the price of being larger.
/// Everything's a tradeoff, a `u64` seed should be sufficient for our
/// purposes (primarily `-Z randomize-layout`)
pub field_shuffle_seed: u64,
}

impl ReprOptions {
@@ -1513,6 +1524,11 @@ impl ReprOptions {
let mut size = None;
let mut max_align: Option<Align> = None;
let mut min_pack: Option<Align> = None;

// Generate a deterministically-derived seed from the item's path hash
// to allow for cross-crate compilation to actually work
let field_shuffle_seed = tcx.def_path_hash(did).0.to_smaller_hash();

for attr in tcx.get_attrs(did).iter() {
for r in attr::find_repr_attrs(&tcx.sess, attr) {
flags.insert(match r {
@@ -1541,33 +1557,45 @@ impl ReprOptions {
}
}

// If `-Z randomize-layout` was enabled for the type definition then we can
// consider performing layout randomization
if tcx.sess.opts.debugging_opts.randomize_layout {
flags.insert(ReprFlags::RANDOMIZE_LAYOUT);
}

// This is here instead of layout because the choice must make it into metadata.
if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.def_path_str(did))) {
flags.insert(ReprFlags::IS_LINEAR);
}
ReprOptions { int: size, align: max_align, pack: min_pack, flags }

Self { int: size, align: max_align, pack: min_pack, flags, field_shuffle_seed }
}

#[inline]
pub fn simd(&self) -> bool {
self.flags.contains(ReprFlags::IS_SIMD)
}

#[inline]
pub fn c(&self) -> bool {
self.flags.contains(ReprFlags::IS_C)
}

#[inline]
pub fn packed(&self) -> bool {
self.pack.is_some()
}

#[inline]
pub fn transparent(&self) -> bool {
self.flags.contains(ReprFlags::IS_TRANSPARENT)
}

#[inline]
pub fn linear(&self) -> bool {
self.flags.contains(ReprFlags::IS_LINEAR)
}

#[inline]
pub fn hide_niche(&self) -> bool {
self.flags.contains(ReprFlags::HIDE_NICHE)
@@ -1594,9 +1622,17 @@ impl ReprOptions {
return true;
}
}

self.flags.intersects(ReprFlags::IS_UNOPTIMISABLE) || self.int.is_some()
}

/// Returns `true` if this type is valid for reordering and `-Z randomize-layout`
/// was enabled for its declaration crate
pub fn can_randomize_type_layout(&self) -> bool {
!self.inhibit_struct_field_reordering_opt()
&& self.flags.contains(ReprFlags::RANDOMIZE_LAYOUT)
}

/// Returns `true` if this `#[repr()]` should inhibit union ABI optimisations.
pub fn inhibit_union_abi_opt(&self) -> bool {
self.c()
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/inline.rs
Original file line number Diff line number Diff line change
@@ -147,7 +147,7 @@ impl Inliner<'tcx> {
self.check_mir_body(callsite, callee_body, callee_attrs)?;

if !self.tcx.consider_optimizing(|| {
format!("Inline {:?} into {}", callee_body.span, callsite.callee)
format!("Inline {:?} into {:?}", callsite.callee, caller_body.source)
}) {
return Err("optimization fuel exhausted");
}
37 changes: 32 additions & 5 deletions compiler/rustc_parse/src/parser/path.rs
Original file line number Diff line number Diff line change
@@ -495,20 +495,28 @@ impl<'a> Parser<'a> {
None => {
let after_eq = eq.shrink_to_hi();
let before_next = self.token.span.shrink_to_lo();
self.struct_span_err(after_eq.to(before_next), "missing type to the right of `=`")
.span_suggestion(
let mut err = self
.struct_span_err(after_eq.to(before_next), "missing type to the right of `=`");
if matches!(self.token.kind, token::Comma | token::Gt) {
err.span_suggestion(
self.sess.source_map().next_point(eq).to(before_next),
"to constrain the associated type, add a type after `=`",
" TheType".to_string(),
Applicability::HasPlaceholders,
)
.span_suggestion(
);
err.span_suggestion(
eq.to(before_next),
&format!("remove the `=` if `{}` is a type", ident),
String::new(),
Applicability::MaybeIncorrect,
)
.emit();
} else {
err.span_label(
self.token.span,
&format!("expected type, found {}", super::token_descr(&self.token)),
)
};
return Err(err);
}
}
Ok(self.mk_ty(span, ast::TyKind::Err))
@@ -572,6 +580,25 @@ impl<'a> Parser<'a> {
return self.recover_const_arg(start, err).map(Some);
}
}
} else if self.eat_keyword_noexpect(kw::Const) {
// Detect and recover from the old, pre-RFC2000 syntax for const generics.
let mut err = self.struct_span_err(
start,
"expected lifetime, type, or constant, found keyword `const`",
);
if self.check_const_arg() {
err.span_suggestion_verbose(
start.until(self.token.span),
"the `const` keyword is only needed in the definition of the type",
String::new(),
Applicability::MaybeIncorrect,
);
err.emit();
GenericArg::Const(self.parse_const_arg()?)
} else {
let after_kw_const = self.token.span;
return self.recover_const_arg(after_kw_const, err).map(Some);
}
} else {
return Ok(None);
};
2 changes: 2 additions & 0 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
@@ -1246,6 +1246,8 @@ options! {
"enable queries of the dependency graph for regression testing (default: no)"),
query_stats: bool = (false, parse_bool, [UNTRACKED],
"print some statistics about the query system (default: no)"),
randomize_layout: bool = (false, parse_bool, [TRACKED],
"randomize the layout of types (default: no)"),
relax_elf_relocations: Option<bool> = (None, parse_opt_bool, [TRACKED],
"whether ELF relocations can be relaxed"),
relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
7 changes: 1 addition & 6 deletions compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
@@ -162,9 +162,6 @@ pub struct Session {
/// Data about code being compiled, gathered during compilation.
pub code_stats: CodeStats,

/// If `-zfuel=crate=n` is specified, `Some(crate)`.
optimization_fuel_crate: Option<String>,

/// Tracks fuel info if `-zfuel=crate=n` is specified.
optimization_fuel: Lock<OptimizationFuel>,

@@ -882,7 +879,7 @@ impl Session {
/// This expends fuel if applicable, and records fuel if applicable.
pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -> bool {
let mut ret = true;
if let Some(ref c) = self.optimization_fuel_crate {
if let Some((ref c, _)) = self.opts.debugging_opts.fuel {
if c == crate_name {
assert_eq!(self.threads(), 1);
let mut fuel = self.optimization_fuel.lock();
@@ -1260,7 +1257,6 @@ pub fn build_session(
let local_crate_source_file =
local_crate_source_file.map(|path| file_path_mapping.map_prefix(path).0);

let optimization_fuel_crate = sopts.debugging_opts.fuel.as_ref().map(|i| i.0.clone());
let optimization_fuel = Lock::new(OptimizationFuel {
remaining: sopts.debugging_opts.fuel.as_ref().map_or(0, |i| i.1),
out_of_fuel: false,
@@ -1311,7 +1307,6 @@ pub fn build_session(
normalize_projection_ty: AtomicUsize::new(0),
},
code_stats: Default::default(),
optimization_fuel_crate,
optimization_fuel,
print_fuel,
jobserver: jobserver::client(),
3 changes: 3 additions & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
@@ -288,6 +288,7 @@ impl ToJson for MergeFunctions {
pub enum RelocModel {
Static,
Pic,
Pie,
DynamicNoPic,
Ropi,
Rwpi,
@@ -301,6 +302,7 @@ impl FromStr for RelocModel {
Ok(match s {
"static" => RelocModel::Static,
"pic" => RelocModel::Pic,
"pie" => RelocModel::Pie,
"dynamic-no-pic" => RelocModel::DynamicNoPic,
"ropi" => RelocModel::Ropi,
"rwpi" => RelocModel::Rwpi,
@@ -315,6 +317,7 @@ impl ToJson for RelocModel {
match *self {
RelocModel::Static => "static",
RelocModel::Pic => "pic",
RelocModel::Pie => "pie",
RelocModel::DynamicNoPic => "dynamic-no-pic",
RelocModel::Ropi => "ropi",
RelocModel::Rwpi => "rwpi",
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/astconv/generics.rs
Original file line number Diff line number Diff line change
@@ -600,7 +600,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
def_id,
)
.diagnostic()
.emit();
.emit_unless(gen_args.has_err());

false
};
4 changes: 4 additions & 0 deletions src/doc/rustc/src/codegen-options/index.md
Original file line number Diff line number Diff line change
@@ -435,6 +435,10 @@ Equivalent to the "uppercase" `-fPIC` or `-fPIE` options in other compilers,
depending on the produced crate types. \
This is the default model for majority of supported targets.

- `pie` - position independent executable, relocatable code but without support for symbol
interpositioning (replacing symbols by name using `LD_PRELOAD` and similar). Equivalent to the "uppercase" `-fPIE` option in other compilers. `pie`
code cannot be linked into shared libraries (you'll get a linking error on attempt to do this).

#### Special relocation models

- `dynamic-no-pic` - relocatable external references, non-relocatable code. \
35 changes: 35 additions & 0 deletions src/test/assembly/pic-relocation-model.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// revisions: x64
// assembly-output: emit-asm
// [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=pic
// [x64] needs-llvm-components: x86


#![feature(no_core, lang_items)]
#![no_core]
#![crate_type="rlib"]

#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}

// CHECK-LABEL: call_other_fn:
// CHECK: {{(jmpq|callq)}} *other_fn@GOTPCREL(%rip)
#[no_mangle]
pub fn call_other_fn() -> u8 {
unsafe {
other_fn()
}
}

// CHECK-LABEL: other_fn:
// CHECK: callq *foreign_fn@GOTPCREL(%rip)
#[no_mangle]
#[inline(never)]
pub fn other_fn() -> u8 {
unsafe {
foreign_fn()
}
}

extern "C" {fn foreign_fn() -> u8;}
38 changes: 38 additions & 0 deletions src/test/assembly/pie-relocation-model.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// revisions: x64
// assembly-output: emit-asm
// [x64] compile-flags: --target x86_64-unknown-linux-gnu -Crelocation-model=pie
// [x64] needs-llvm-components: x86


#![feature(no_core, lang_items)]
#![no_core]
#![crate_type="rlib"]

#[lang = "sized"]
trait Sized {}
#[lang = "copy"]
trait Copy {}

// CHECK-LABEL: call_other_fn:
// With PIE local functions are called "directly".
// CHECK: {{(jmp|callq)}} other_fn
#[no_mangle]
pub fn call_other_fn() -> u8 {
unsafe {
other_fn()
}
}

// CHECK-LABEL: other_fn:
// External functions are still called through GOT, since we don't know if the symbol
// is defined in the binary or in the shared library.
// CHECK: callq *foreign_fn@GOTPCREL(%rip)
#[no_mangle]
#[inline(never)]
pub fn other_fn() -> u8 {
unsafe {
foreign_fn()
}
}

extern "C" {fn foreign_fn() -> u8;}
16 changes: 16 additions & 0 deletions src/test/codegen/pic-relocation-model.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// compile-flags: -C relocation-model=pic

#![crate_type = "rlib"]

// CHECK: define i8 @call_foreign_fn()
#[no_mangle]
pub fn call_foreign_fn() -> u8 {
unsafe {
foreign_fn()
}
}

// CHECK: declare zeroext i8 @foreign_fn()
extern "C" {fn foreign_fn() -> u8;}

// CHECK: !{i32 7, !"PIC Level", i32 2}
22 changes: 22 additions & 0 deletions src/test/codegen/pie-relocation-model.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// compile-flags: -C relocation-model=pie
// only-x86_64-unknown-linux-gnu

#![crate_type = "rlib"]

// With PIE we know local functions cannot be interpositioned, we can mark them
// as dso_local.
// CHECK: define dso_local i8 @call_foreign_fn()
#[no_mangle]
pub fn call_foreign_fn() -> u8 {
unsafe {
foreign_fn()
}
}

// External functions are still marked as non-dso_local, since we don't know if the symbol
// is defined in the binary or in the shared library.
// CHECK: declare zeroext i8 @foreign_fn()
extern "C" {fn foreign_fn() -> u8;}

// CHECK: !{i32 7, !"PIC Level", i32 2}
// CHECK: !{i32 7, !"PIE Level", i32 2}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
trait Foo<const N: usize> {
fn do_x(&self) -> [u8; N];
}

struct Bar;

const T: usize = 42;

impl Foo<const 3> for Bar {
//~^ERROR expected lifetime, type, or constant, found keyword `const`
fn do_x(&self) -> [u8; 3] {
[0u8; 3]
}
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: expected lifetime, type, or constant, found keyword `const`
--> $DIR/issue-89013-no-assoc.rs:9:10
|
LL | impl Foo<const 3> for Bar {
| ^^^^^
|
help: the `const` keyword is only needed in the definition of the type
|
LL - impl Foo<const 3> for Bar {
LL + impl Foo<3> for Bar {
|

error: aborting due to previous error

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
trait Foo<const N: usize> {
fn do_x(&self) -> [u8; N];
}

struct Bar;

const T: usize = 42;

impl Foo<N = 3> for Bar {
//~^ ERROR cannot constrain an associated constant to a value
//~| ERROR associated type bindings are not allowed here
fn do_x(&self) -> [u8; 3] {
[0u8; 3]
}
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error: cannot constrain an associated constant to a value
--> $DIR/issue-89013-no-kw.rs:9:10
|
LL | impl Foo<N = 3> for Bar {
| -^^^-
| | |
| | ...cannot be constrained to this value
| this associated constant...

error[E0229]: associated type bindings are not allowed here
--> $DIR/issue-89013-no-kw.rs:9:10
|
LL | impl Foo<N = 3> for Bar {
| ^^^^^ associated type not allowed here

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0229`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
trait Foo<const N: usize> {
fn do_x(&self) -> [u8; N];
}

struct Bar;

const T: usize = 42;

impl Foo<N = type 3> for Bar {
//~^ERROR missing type to the right of `=`
fn do_x(&self) -> [u8; 3] {
[0u8; 3]
}
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: missing type to the right of `=`
--> $DIR/issue-89013-type.rs:9:13
|
LL | impl Foo<N = type 3> for Bar {
| ^---- expected type, found keyword `type`

error: aborting due to previous error

18 changes: 18 additions & 0 deletions src/test/ui/const-generics/parser-error-recovery/issue-89013.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
trait Foo<const N: usize> {
fn do_x(&self) -> [u8; N];
}

struct Bar;

const T: usize = 42;

impl Foo<N = const 3> for Bar {
//~^ ERROR expected lifetime, type, or constant, found keyword `const`
//~| ERROR cannot constrain an associated constant to a value
//~| ERROR associated type bindings are not allowed here
fn do_x(&self) -> [u8; 3] {
[0u8; 3]
}
}

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
error: expected lifetime, type, or constant, found keyword `const`
--> $DIR/issue-89013.rs:9:14
|
LL | impl Foo<N = const 3> for Bar {
| ^^^^^
|
help: the `const` keyword is only needed in the definition of the type
|
LL - impl Foo<N = const 3> for Bar {
LL + impl Foo<N = 3> for Bar {
|

error: cannot constrain an associated constant to a value
--> $DIR/issue-89013.rs:9:10
|
LL | impl Foo<N = const 3> for Bar {
| -^^^^^^^^^-
| | |
| | ...cannot be constrained to this value
| this associated constant...

error[E0229]: associated type bindings are not allowed here
--> $DIR/issue-89013.rs:9:10
|
LL | impl Foo<N = const 3> for Bar {
| ^^^^^^^^^^^ associated type not allowed here

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0229`.
14 changes: 14 additions & 0 deletions src/test/ui/fmt/issue-89173.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Regression test for #89173: Make sure a helpful note is issued for
// printf-style format strings using `*` to specify the width.

fn main() {
let num = 0x0abcde;
let width = 6;
print!("%0*x", width, num);
//~^ ERROR: multiple unused formatting arguments
//~| NOTE: multiple missing formatting specifiers
//~| NOTE: argument never used
//~| NOTE: argument never used
//~| NOTE: format specifiers use curly braces, and you have to use a positional or named parameter for the width
//~| NOTE: printf formatting not supported
}
18 changes: 18 additions & 0 deletions src/test/ui/fmt/issue-89173.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
error: multiple unused formatting arguments
--> $DIR/issue-89173.rs:7:20
|
LL | print!("%0*x", width, num);
| ------ ^^^^^ ^^^ argument never used
| | |
| | argument never used
| multiple missing formatting specifiers
|
note: format specifiers use curly braces, and you have to use a positional or named parameter for the width
--> $DIR/issue-89173.rs:7:13
|
LL | print!("%0*x", width, num);
| ^^^^
= note: printf formatting not supported; see the documentation for `std::fmt`

error: aborting due to previous error

1 change: 1 addition & 0 deletions src/tools/tidy/src/deps.rs
Original file line number Diff line number Diff line change
@@ -167,6 +167,7 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[
"rand_hc",
"rand_pcg",
"rand_xorshift",
"rand_xoshiro",
"redox_syscall",
"regex",
"regex-automata",