Auto merge of #76786 - Dylan-DPC:rollup-x6p60m6, r=Dylan-DPC

Rollup of 10 pull requests

Successful merges:

 - #76669 (Prefer asm! over llvm_asm! in core)
 - #76675 (Small improvements to asm documentation)
 - #76681 (remove orphaned files)
 - #76694 (Introduce a PartitioningCx struct)
 - #76695 (fix syntax error in suggesting generic constraint in trait parameter)
 - #76699 (improve const infer error)
 - #76707 (Simplify iter flatten struct doc)
 - #76710 (⬆️ rust-analyzer)
 - #76714 (Small docs improvements)
 - #76717 (Fix generating rustc docs with non-default lib directory.)

Failed merges:

r? `@ghost`
This commit is contained in:
bors 2020-09-16 13:23:46 +00:00
commit 7bb106fe63
35 changed files with 291 additions and 156 deletions

View File

@ -6,9 +6,10 @@
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, Pat};
use rustc_middle::hir::map::Map;
use rustc_middle::infer::unify_key::ConstVariableOriginKind;
use rustc_middle::ty::print::Print;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
use rustc_middle::ty::{self, DefIdTree, Ty};
use rustc_middle::ty::{self, DefIdTree, InferConst, Ty};
use rustc_span::source_map::DesugaringKind;
use rustc_span::symbol::kw;
use rustc_span::Span;
@ -569,14 +570,26 @@ pub fn need_type_info_err_const(
local_visitor.visit_expr(expr);
}
let error_code = error_code.into();
let mut err = self.tcx.sess.struct_span_err_with_code(
local_visitor.target_span,
"type annotations needed",
error_code,
);
let mut param_name = None;
let span = if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val {
let origin = self.inner.borrow_mut().const_unification_table().probe_value(vid).origin;
if let ConstVariableOriginKind::ConstParameterDefinition(param) = origin.kind {
param_name = Some(param);
}
origin.span
} else {
local_visitor.target_span
};
err.note("unable to infer the value of a const parameter");
let error_code = error_code.into();
let mut err =
self.tcx.sess.struct_span_err_with_code(span, "type annotations needed", error_code);
if let Some(param_name) = param_name {
err.note(&format!("cannot infer the value of the const parameter `{}`", param_name));
} else {
err.note("unable to infer the value of a const parameter");
}
err
}

View File

@ -124,6 +124,7 @@ pub struct ConstVariableOrigin {
pub enum ConstVariableOriginKind {
MiscVariable,
ConstInference,
// FIXME(const_generics): Consider storing the `DefId` of the param here.
ConstParameterDefinition(Symbol),
SubstitutionPlaceholder,
}

View File

@ -2285,8 +2285,8 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
/// Constants
///
/// Two constants are equal if they are the same constant. Note that
/// this does not necessarily mean that they are "==" in Rust -- in
/// particular one must be wary of `NaN`!
/// this does not necessarily mean that they are `==` in Rust -- in
/// particular, one must be wary of `NaN`!
#[derive(Clone, Copy, PartialEq, TyEncodable, TyDecodable, HashStable)]
pub struct Constant<'tcx> {

View File

@ -66,8 +66,8 @@
use std::ops::{Bound, Deref};
use std::sync::Arc;
/// A type that is not publicly constructable. This prevents people from making `TyKind::Error`
/// except through `tcx.err*()`, which are in this module.
/// A type that is not publicly constructable. This prevents people from making [`TyKind::Error`]s
/// except through the error-reporting functions on a [`tcx`][TyCtxt].
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
#[derive(TyEncodable, TyDecodable, HashStable)]
pub struct DelaySpanBugEmitted(());

View File

@ -202,33 +202,59 @@ pub fn suggest_constraining_type_param(
// Suggestion:
// fn foo<T>(t: T) where T: Foo, T: Bar {... }
// - insert: `, T: Zar`
//
// Additionally, there may be no `where` clause whatsoever in the case that this was
// reached because the generic parameter has a default:
//
// Message:
// trait Foo<T=()> {... }
// - help: consider further restricting this type parameter with `where T: Zar`
//
// Suggestion:
// trait Foo<T=()> where T: Zar {... }
// - insert: `where T: Zar`
let mut param_spans = Vec::new();
if matches!(param.kind, hir::GenericParamKind::Type { default: Some(_), .. })
&& generics.where_clause.predicates.len() == 0
{
// Suggest a bound, but there is no existing `where` clause *and* the type param has a
// default (`<T=Foo>`), so we suggest adding `where T: Bar`.
err.span_suggestion_verbose(
generics.where_clause.tail_span_for_suggestion(),
&msg_restrict_type_further,
format!(" where {}: {}", param_name, constraint),
Applicability::MachineApplicable,
);
} else {
let mut param_spans = Vec::new();
for predicate in generics.where_clause.predicates {
if let WherePredicate::BoundPredicate(WhereBoundPredicate {
span, bounded_ty, ..
}) = predicate
{
if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind {
if let Some(segment) = path.segments.first() {
if segment.ident.to_string() == param_name {
param_spans.push(span);
for predicate in generics.where_clause.predicates {
if let WherePredicate::BoundPredicate(WhereBoundPredicate {
span,
bounded_ty,
..
}) = predicate
{
if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind {
if let Some(segment) = path.segments.first() {
if segment.ident.to_string() == param_name {
param_spans.push(span);
}
}
}
}
}
}
match &param_spans[..] {
&[&param_span] => suggest_restrict(param_span.shrink_to_hi()),
_ => {
err.span_suggestion_verbose(
generics.where_clause.tail_span_for_suggestion(),
&msg_restrict_type_further,
format!(", {}: {}", param_name, constraint),
Applicability::MachineApplicable,
);
match &param_spans[..] {
&[&param_span] => suggest_restrict(param_span.shrink_to_hi()),
_ => {
err.span_suggestion_verbose(
generics.where_clause.tail_span_for_suggestion(),
&msg_restrict_type_further,
format!(", {}: {}", param_name, constraint),
Applicability::MachineApplicable,
);
}
}
}

View File

@ -1233,13 +1233,13 @@ pub fn to_const(self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx>
/// particular, imagine a type like this:
///
/// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char)
/// ^ ^ | | |
/// | | | | |
/// | +------------+ 0 | |
/// | | |
/// +--------------------------------+ 1 |
/// | |
/// +------------------------------------------+ 0
/// ^ ^ | | |
/// | | | | |
/// | +------------+ 0 | |
/// | | |
/// +----------------------------------+ 1 |
/// | |
/// +----------------------------------------------+ 0
///
/// In this type, there are two binders (the outer fn and the inner
/// fn). We need to be able to determine, for any given region, which

View File

@ -11,6 +11,7 @@
use rustc_middle::ty::{self, DefIdTree, InstanceDef, TyCtxt};
use rustc_span::symbol::Symbol;
use super::PartitioningCx;
use crate::monomorphize::collector::InliningMap;
use crate::monomorphize::partitioning::merging;
use crate::monomorphize::partitioning::{
@ -22,35 +23,36 @@
impl<'tcx> Partitioner<'tcx> for DefaultPartitioning {
fn place_root_mono_items(
&mut self,
tcx: TyCtxt<'tcx>,
cx: &PartitioningCx<'_, 'tcx>,
mono_items: &mut dyn Iterator<Item = MonoItem<'tcx>>,
) -> PreInliningPartitioning<'tcx> {
let mut roots = FxHashSet::default();
let mut codegen_units = FxHashMap::default();
let is_incremental_build = tcx.sess.opts.incremental.is_some();
let is_incremental_build = cx.tcx.sess.opts.incremental.is_some();
let mut internalization_candidates = FxHashSet::default();
// Determine if monomorphizations instantiated in this crate will be made
// available to downstream crates. This depends on whether we are in
// share-generics mode and whether the current crate can even have
// downstream crates.
let export_generics = tcx.sess.opts.share_generics() && tcx.local_crate_exports_generics();
let export_generics =
cx.tcx.sess.opts.share_generics() && cx.tcx.local_crate_exports_generics();
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
let cgu_name_cache = &mut FxHashMap::default();
for mono_item in mono_items {
match mono_item.instantiation_mode(tcx) {
match mono_item.instantiation_mode(cx.tcx) {
InstantiationMode::GloballyShared { .. } => {}
InstantiationMode::LocalCopy => continue,
}
let characteristic_def_id = characteristic_def_id_of_mono_item(tcx, mono_item);
let characteristic_def_id = characteristic_def_id_of_mono_item(cx.tcx, mono_item);
let is_volatile = is_incremental_build && mono_item.is_generic_fn();
let codegen_unit_name = match characteristic_def_id {
Some(def_id) => compute_codegen_unit_name(
tcx,
cx.tcx,
cgu_name_builder,
def_id,
is_volatile,
@ -65,7 +67,7 @@ fn place_root_mono_items(
let mut can_be_internalized = true;
let (linkage, visibility) = mono_item_linkage_and_visibility(
tcx,
cx.tcx,
&mono_item,
&mut can_be_internalized,
export_generics,
@ -97,17 +99,16 @@ fn place_root_mono_items(
fn merge_codegen_units(
&mut self,
tcx: TyCtxt<'tcx>,
cx: &PartitioningCx<'_, 'tcx>,
initial_partitioning: &mut PreInliningPartitioning<'tcx>,
target_cgu_count: usize,
) {
merging::merge_codegen_units(tcx, initial_partitioning, target_cgu_count);
merging::merge_codegen_units(cx, initial_partitioning);
}
fn place_inlined_mono_items(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
initial_partitioning: PreInliningPartitioning<'tcx>,
inlining_map: &InliningMap<'tcx>,
) -> PostInliningPartitioning<'tcx> {
let mut new_partitioning = Vec::new();
let mut mono_item_placements = FxHashMap::default();
@ -124,7 +125,7 @@ fn place_inlined_mono_items(
// Collect all items that need to be available in this codegen unit.
let mut reachable = FxHashSet::default();
for root in old_codegen_unit.items().keys() {
follow_inlining(*root, inlining_map, &mut reachable);
follow_inlining(*root, cx.inlining_map, &mut reachable);
}
let mut new_codegen_unit = CodegenUnit::new(old_codegen_unit.name());
@ -198,9 +199,8 @@ fn follow_inlining<'tcx>(
fn internalize_symbols(
&mut self,
_tcx: TyCtxt<'tcx>,
cx: &PartitioningCx<'_, 'tcx>,
partitioning: &mut PostInliningPartitioning<'tcx>,
inlining_map: &InliningMap<'tcx>,
) {
if partitioning.codegen_units.len() == 1 {
// Fast path for when there is only one codegen unit. In this case we
@ -218,7 +218,7 @@ fn internalize_symbols(
// Build a map from every monomorphization to all the monomorphizations that
// reference it.
let mut accessor_map: FxHashMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>> = Default::default();
inlining_map.iter_accesses(|accessor, accessees| {
cx.inlining_map.iter_accesses(|accessor, accessees| {
for accessee in accessees {
accessor_map.entry(*accessee).or_default().push(accessor);
}

View File

@ -3,17 +3,16 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder};
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::{Symbol, SymbolStr};
use super::PartitioningCx;
use crate::monomorphize::partitioning::PreInliningPartitioning;
pub fn merge_codegen_units<'tcx>(
tcx: TyCtxt<'tcx>,
cx: &PartitioningCx<'_, 'tcx>,
initial_partitioning: &mut PreInliningPartitioning<'tcx>,
target_cgu_count: usize,
) {
assert!(target_cgu_count >= 1);
assert!(cx.target_cgu_count >= 1);
let codegen_units = &mut initial_partitioning.codegen_units;
// Note that at this point in time the `codegen_units` here may not be in a
@ -32,7 +31,7 @@ pub fn merge_codegen_units<'tcx>(
codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name().as_str()])).collect();
// Merge the two smallest codegen units until the target size is reached.
while codegen_units.len() > target_cgu_count {
while codegen_units.len() > cx.target_cgu_count {
// Sort small cgus to the back
codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
let mut smallest = codegen_units.pop().unwrap();
@ -56,9 +55,9 @@ pub fn merge_codegen_units<'tcx>(
);
}
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx);
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
if tcx.sess.opts.incremental.is_some() {
if cx.tcx.sess.opts.incremental.is_some() {
// If we are doing incremental compilation, we want CGU names to
// reflect the path of the source level module they correspond to.
// For CGUs that contain the code of multiple modules because of the
@ -84,7 +83,7 @@ pub fn merge_codegen_units<'tcx>(
for cgu in codegen_units.iter_mut() {
if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) {
if tcx.sess.opts.debugging_opts.human_readable_cgu_names {
if cx.tcx.sess.opts.debugging_opts.human_readable_cgu_names {
cgu.set_name(Symbol::intern(&new_cgu_name));
} else {
// If we don't require CGU names to be human-readable, we

View File

@ -108,31 +108,35 @@
use crate::monomorphize::collector::InliningMap;
use crate::monomorphize::collector::{self, MonoItemCollectionMode};
pub struct PartitioningCx<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
target_cgu_count: usize,
inlining_map: &'a InliningMap<'tcx>,
}
trait Partitioner<'tcx> {
fn place_root_mono_items(
&mut self,
tcx: TyCtxt<'tcx>,
cx: &PartitioningCx<'_, 'tcx>,
mono_items: &mut dyn Iterator<Item = MonoItem<'tcx>>,
) -> PreInliningPartitioning<'tcx>;
fn merge_codegen_units(
&mut self,
tcx: TyCtxt<'tcx>,
cx: &PartitioningCx<'_, 'tcx>,
initial_partitioning: &mut PreInliningPartitioning<'tcx>,
target_cgu_count: usize,
);
fn place_inlined_mono_items(
&mut self,
cx: &PartitioningCx<'_, 'tcx>,
initial_partitioning: PreInliningPartitioning<'tcx>,
inlining_map: &InliningMap<'tcx>,
) -> PostInliningPartitioning<'tcx>;
fn internalize_symbols(
&mut self,
tcx: TyCtxt<'tcx>,
cx: &PartitioningCx<'_, 'tcx>,
partitioning: &mut PostInliningPartitioning<'tcx>,
inlining_map: &InliningMap<'tcx>,
);
}
@ -157,12 +161,13 @@ pub fn partition<'tcx>(
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning");
let mut partitioner = get_partitioner(tcx);
let cx = &PartitioningCx { tcx, target_cgu_count: max_cgu_count, inlining_map };
// In the first step, we place all regular monomorphizations into their
// respective 'home' codegen unit. Regular monomorphizations are all
// functions and statics defined in the local crate.
let mut initial_partitioning = {
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots");
partitioner.place_root_mono_items(tcx, mono_items)
partitioner.place_root_mono_items(cx, mono_items)
};
initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx));
@ -172,7 +177,7 @@ pub fn partition<'tcx>(
// Merge until we have at most `max_cgu_count` codegen units.
{
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus");
partitioner.merge_codegen_units(tcx, &mut initial_partitioning, max_cgu_count);
partitioner.merge_codegen_units(cx, &mut initial_partitioning);
debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter());
}
@ -182,7 +187,7 @@ pub fn partition<'tcx>(
// local functions the definition of which is marked with `#[inline]`.
let mut post_inlining = {
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_inline_items");
partitioner.place_inlined_mono_items(initial_partitioning, inlining_map)
partitioner.place_inlined_mono_items(cx, initial_partitioning)
};
post_inlining.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx));
@ -193,7 +198,7 @@ pub fn partition<'tcx>(
// more freedom to optimize.
if !tcx.sess.link_dead_code() {
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols");
partitioner.internalize_symbols(tcx, &mut post_inlining, inlining_map);
partitioner.internalize_symbols(cx, &mut post_inlining);
}
// Finally, sort by codegen unit name, so that we get deterministic results.

View File

@ -111,7 +111,7 @@ pub fn spin_loop() {
#[inline]
#[unstable(feature = "test", issue = "50297")]
#[allow(unreachable_code)] // this makes #[cfg] a bit easier below.
pub fn black_box<T>(dummy: T) -> T {
pub fn black_box<T>(mut dummy: T) -> T {
// We need to "use" the argument in some way LLVM can't introspect, and on
// targets that support it we can typically leverage inline assembly to do
// this. LLVM's interpretation of inline assembly is that it's, well, a black
@ -121,7 +121,8 @@ pub fn black_box<T>(dummy: T) -> T {
#[cfg(not(miri))] // This is just a hint, so it is fine to skip in Miri.
// SAFETY: the inline assembly is a no-op.
unsafe {
llvm_asm!("" : : "r"(&dummy));
// FIXME: Cannot use `asm!` because it doesn't support MIPS and other architectures.
llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile");
}
dummy

View File

@ -7,11 +7,8 @@
/// An iterator that maps each element to an iterator, and yields the elements
/// of the produced iterators.
///
/// This `struct` is created by the [`flat_map`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`flat_map`]: trait.Iterator.html#method.flat_map
/// [`Iterator`]: trait.Iterator.html
/// This `struct` is created by [`Iterator::flat_map`]. See its documentation
/// for more.
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct FlatMap<I, U: IntoIterator, F> {

View File

@ -60,12 +60,19 @@ mod fpu_precision {
fn set_cw(cw: u16) {
// SAFETY: the `fldcw` instruction has been audited to be able to work correctly with
// any `u16`
unsafe { llvm_asm!("fldcw $0" :: "m" (cw) :: "volatile") }
unsafe {
asm!(
"fldcw ({})",
in(reg) &cw,
// FIXME: We are using ATT syntax to support LLVM 8 and LLVM 9.
options(att_syntax, nostack),
)
}
}
/// Sets the precision field of the FPU to `T` and returns a `FPUControlWord`.
pub fn set_precision<T>() -> FPUControlWord {
let cw = 0u16;
let mut cw = 0_u16;
// Compute the value for the Precision Control field that is appropriate for `T`.
let cw_precision = match size_of::<T>() {
@ -78,7 +85,14 @@ pub fn set_precision<T>() -> FPUControlWord {
// `FPUControlWord` structure is dropped
// SAFETY: the `fnstcw` instruction has been audited to be able to work correctly with
// any `u16`
unsafe { llvm_asm!("fnstcw $0" : "=*m" (&cw) ::: "volatile") }
unsafe {
asm!(
"fnstcw ({})",
in(reg) &mut cw,
// FIXME: We are using ATT syntax to support LLVM 8 and LLVM 9.
options(att_syntax, nostack),
)
}
// Set the control word to the desired precision. This is achieved by masking away the old
// precision (bits 8 and 9, 0x300) and replacing it with the precision flag computed above.

View File

@ -683,7 +683,7 @@ pub fn sysroot_libdir_relative(&self, compiler: Compiler) -> &Path {
/// Adds the compiler's directory of dynamic libraries to `cmd`'s dynamic
/// library lookup path.
pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Cargo) {
pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Command) {
// Windows doesn't need dylib path munging because the dlls for the
// compiler live next to the compiler and the system will find them
// automatically.
@ -691,7 +691,7 @@ pub fn add_rustc_lib_path(&self, compiler: Compiler, cmd: &mut Cargo) {
return;
}
add_dylib_path(vec![self.rustc_libdir(compiler)], &mut cmd.command);
add_dylib_path(vec![self.rustc_libdir(compiler)], cmd);
}
/// Gets a path to the compiler specified.
@ -1488,6 +1488,10 @@ pub fn env(&mut self, key: impl AsRef<OsStr>, value: impl AsRef<OsStr>) -> &mut
self.command.env(key.as_ref(), value.as_ref());
self
}
pub fn add_rustc_lib_path(&mut self, builder: &Builder<'_>, compiler: Compiler) {
builder.add_rustc_lib_path(compiler, &mut self.command);
}
}
impl From<Cargo> for Command {

View File

@ -766,6 +766,10 @@ fn run(self, builder: &Builder<'_>) {
if builder.config.verbose() {
cmd.arg("--verbose");
}
// If the lib directories are in an unusual location (changed in
// config.toml), then this needs to explicitly update the dylib search
// path.
builder.add_rustc_lib_path(self.compiler, &mut cmd);
builder.run(&mut cmd);
// Run rustbook/mdbook to generate the HTML pages.
builder.ensure(RustbookSrc {

View File

@ -270,7 +270,7 @@ fn run(self, builder: &Builder<'_>) {
&[],
);
builder.add_rustc_lib_path(compiler, &mut cargo);
cargo.add_rustc_lib_path(builder, compiler);
cargo.arg("--").args(builder.config.cmd.test_args());
if try_run(builder, &mut cargo.into()) {
@ -328,7 +328,7 @@ fn run(self, builder: &Builder<'_>) {
t!(fs::create_dir_all(&dir));
cargo.env("RUSTFMT_TEST_DIR", dir);
builder.add_rustc_lib_path(compiler, &mut cargo);
cargo.add_rustc_lib_path(builder, compiler);
if try_run(builder, &mut cargo.into()) {
builder.save_toolstate("rustfmt", ToolState::TestPass);
@ -449,7 +449,7 @@ fn run(self, builder: &Builder<'_>) {
cargo.arg("--").args(builder.config.cmd.test_args());
builder.add_rustc_lib_path(compiler, &mut cargo);
cargo.add_rustc_lib_path(builder, compiler);
if !try_run(builder, &mut cargo.into()) {
return;
@ -554,7 +554,7 @@ fn run(self, builder: &Builder<'_>) {
cargo.arg("--").args(builder.config.cmd.test_args());
builder.add_rustc_lib_path(compiler, &mut cargo);
cargo.add_rustc_lib_path(builder, compiler);
builder.run(&mut cargo.into());
}

View File

@ -1,15 +0,0 @@
#!/usr/bin/env bash
set -ex
source shared.sh
curl -L https://www.kernel.org/pub/software/scm/git/git-2.10.0.tar.gz | tar xzf -
cd git-2.10.0
make configure
hide_output ./configure --prefix=/rustroot
hide_output make -j10
hide_output make install
cd ..
rm -rf git-2.10.0

View File

@ -1,16 +0,0 @@
#!/usr/bin/env bash
set -ex
source shared.sh
curl https://cdn.kernel.org/pub/linux/kernel/v3.x/linux-3.2.84.tar.xz | unxz | tar x
cd linux-3.2.84
hide_output make mrproper
hide_output make INSTALL_HDR_PATH=dest headers_install
find dest/include \( -name .install -o -name ..install.cmd \) -delete
yes | cp -fr dest/include/* /usr/include
cd ..
rm -rf linux-3.2.84

View File

@ -1,21 +0,0 @@
#!/usr/bin/env bash
set -ex
source shared.sh
curl https://www.cpan.org/src/5.0/perl-5.28.0.tar.gz | \
tar xzf -
cd perl-5.28.0
# Gotta do some hackery to tell python about our custom OpenSSL build, but other
# than that fairly normal.
CC=gcc \
CFLAGS='-I /rustroot/include -fgnu89-inline' \
LDFLAGS='-L /rustroot/lib -L /rustroot/lib64' \
hide_output ./configure.gnu
hide_output make -j10
hide_output make install
cd ..
rm -rf perl-5.28.0

View File

@ -345,6 +345,25 @@ The `h` modifier will emit the register name for the high byte of that register
If you use a smaller data type (e.g. `u16`) with an operand and forget the use template modifiers, the compiler will emit a warning and suggest the correct modifier to use.
## Memory address operands
Sometimes assembly instructions require operands passed via memory addresses/memory locations.
You have to manually use the memory address syntax specified by the respectively architectures.
For example, in x86/x86_64 and intel assembly syntax, you should wrap inputs/outputs in `[]`
to indicate they are memory operands:
```rust,allow_fail
# #![feature(asm, llvm_asm)]
# fn load_fpu_control_word(control: u16) {
unsafe {
asm!("fldcw [{}]", in(reg) &control, options(nostack));
// Previously this would have been written with the deprecated `llvm_asm!` like this
llvm_asm!("fldcw $0" :: "m" (control) :: "volatile");
}
# }
```
## Options
By default, an inline assembly block is treated the same way as an external FFI function call with a custom calling convention: it may read/write memory, have observable side effects, etc. However in many cases, it is desirable to give the compiler more information about what the assembly code is actually doing so that it can optimize better.

View File

@ -159,12 +159,12 @@ specify some extra info about the inline assembly:
Current valid options are:
1. *volatile* - specifying this is analogous to
1. `volatile` - specifying this is analogous to
`__asm__ __volatile__ (...)` in gcc/clang.
2. *alignstack* - certain instructions expect the stack to be
2. `alignstack` - certain instructions expect the stack to be
aligned a certain way (i.e. SSE) and specifying this indicates to
the compiler to insert its usual stack alignment code
3. *intel* - use intel syntax instead of the default AT&T.
3. `intel` - use intel syntax instead of the default AT&T.
```rust
# #![feature(llvm_asm)]

View File

@ -4,7 +4,7 @@ error[E0282]: type annotations needed
LL | foo();
| ^^^
|
= note: unable to infer the value of a const parameter
= note: cannot infer the value of the const parameter `X`
error: aborting due to previous error

View File

@ -4,7 +4,7 @@ error[E0282]: type annotations needed
LL | foo();
| ^^^
|
= note: unable to infer the value of a const parameter
= note: cannot infer the value of the const parameter `X`
error: aborting due to previous error

View File

@ -0,0 +1,11 @@
error[E0282]: type annotations needed
--> $DIR/method-chain.rs:21:33
|
LL | Foo.bar().bar().bar().bar().baz();
| ^^^
|
= note: cannot infer the value of the const parameter `N`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0282`.

View File

@ -0,0 +1,11 @@
error[E0282]: type annotations needed
--> $DIR/method-chain.rs:21:33
|
LL | Foo.bar().bar().bar().bar().baz();
| ^^^
|
= note: cannot infer the value of the const parameter `N`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0282`.

View File

@ -0,0 +1,22 @@
// revisions: full min
#![cfg_attr(full, feature(const_generics))]
#![cfg_attr(full, allow(incomplete_features))]
#![cfg_attr(min, feature(min_const_generics))]
struct Foo;
impl Foo {
fn bar(self) -> Foo {
Foo
}
fn baz<const N: usize>(self) -> Foo {
println!("baz: {}", N);
Foo
}
}
fn main() {
Foo.bar().bar().bar().bar().baz(); //~ ERROR type annotations needed
}

View File

@ -1,10 +1,10 @@
error[E0282]: type annotations needed
--> $DIR/uninferred-consts.rs:14:5
--> $DIR/uninferred-consts.rs:14:9
|
LL | Foo.foo();
| ^^^^^^^^^
| ^^^
|
= note: unable to infer the value of a const parameter
= note: cannot infer the value of the const parameter `N`
error: aborting due to previous error

View File

@ -1,10 +1,10 @@
error[E0282]: type annotations needed
--> $DIR/uninferred-consts.rs:14:5
--> $DIR/uninferred-consts.rs:14:9
|
LL | Foo.foo();
| ^^^^^^^^^
| ^^^
|
= note: unable to infer the value of a const parameter
= note: cannot infer the value of the const parameter `N`
error: aborting due to previous error

View File

@ -0,0 +1,20 @@
// run-rustfix
#[allow(unused)]
use std::fmt::Debug;
// Rustfix should add this, or use `std::fmt::Debug` instead.
#[allow(dead_code)]
struct ConstrainedStruct<X: Copy> {
x: X
}
#[allow(dead_code)]
trait InsufficientlyConstrainedGeneric<X=()> where X: Copy {
fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
//~^ ERROR the trait bound `X: Copy` is not satisfied
ConstrainedStruct { x }
}
}
pub fn main() { }

View File

@ -0,0 +1,20 @@
// run-rustfix
#[allow(unused)]
use std::fmt::Debug;
// Rustfix should add this, or use `std::fmt::Debug` instead.
#[allow(dead_code)]
struct ConstrainedStruct<X: Copy> {
x: X
}
#[allow(dead_code)]
trait InsufficientlyConstrainedGeneric<X=()> {
fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
//~^ ERROR the trait bound `X: Copy` is not satisfied
ConstrainedStruct { x }
}
}
pub fn main() { }

View File

@ -0,0 +1,17 @@
error[E0277]: the trait bound `X: Copy` is not satisfied
--> $DIR/trait-impl-bound-suggestions.rs:14:52
|
LL | struct ConstrainedStruct<X: Copy> {
| ---- required by this bound in `ConstrainedStruct`
...
LL | fn return_the_constrained_type(&self, x: X) -> ConstrainedStruct<X> {
| ^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `X`
|
help: consider further restricting type parameter `X`
|
LL | trait InsufficientlyConstrainedGeneric<X=()> where X: Copy {
| ^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.

View File

@ -56,8 +56,8 @@ LL | trait Base<T = String>: Super<T> { }
|
help: consider further restricting type parameter `T`
|
LL | trait Base<T = String>: Super<T>, T: Copy { }
| ^^^^^^^^^
LL | trait Base<T = String>: Super<T> where T: Copy { }
| ^^^^^^^^^^^^^
error[E0277]: cannot add `u8` to `i32`
--> $DIR/type-check-defaults.rs:24:66

View File

@ -402,9 +402,12 @@ fn generate_lint_output(
None => {
let rendered: Vec<&str> =
msgs.iter().filter_map(|msg| msg["rendered"].as_str()).collect();
let non_json: Vec<&str> =
stderr.lines().filter(|line| !line.starts_with('{')).collect();
Err(format!(
"did not find lint `{}` in output of example, got:\n{}",
"did not find lint `{}` in output of example, got:\n{}\n{}",
name,
non_json.join("\n"),
rendered.join("\n")
)
.into())

@ -1 +1 @@
Subproject commit 0275b08d1521606fa733f76fe5d5707717456fb4
Subproject commit 0d03fe6ef57d3956e92382e0e1f1a916015191cb