Auto merge of #68405 - JohnTitor:rollup-kj0x4za, r=JohnTitor
Rollup of 8 pull requests Successful merges: - #67734 (Remove appendix from Apache license) - #67795 (Cleanup formatting code) - #68290 (Fix some tests failing in `--pass check` mode) - #68297 ( Filter and test predicates using `normalize_and_test_predicates` for const-prop) - #68302 (Fix #[track_caller] and function pointers) - #68339 (Add `riscv64gc-unknown-linux-gnu` into target list in build-manifest) - #68381 (Added minor clarification to specification of GlobalAlloc::realloc.) - #68397 (rustdoc: Correct order of `async` and `unsafe` in `async unsafe fn`s) Failed merges: r? @ghost
This commit is contained in:
commit
06b945049b
27 changed files with 269 additions and 245 deletions
|
@ -174,28 +174,3 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
of your accepting any such warranty or additional liability.
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
|
@ -525,7 +525,8 @@ pub unsafe trait GlobalAlloc {
|
||||||
/// The memory may or may not have been deallocated,
|
/// The memory may or may not have been deallocated,
|
||||||
/// and should be considered unusable (unless of course it was
|
/// and should be considered unusable (unless of course it was
|
||||||
/// transferred back to the caller again via the return value of
|
/// transferred back to the caller again via the return value of
|
||||||
/// this method).
|
/// this method). The new memory block is allocated with `layout`, but
|
||||||
|
/// with the `size` updated to `new_size`.
|
||||||
///
|
///
|
||||||
/// If this method returns null, then ownership of the memory
|
/// If this method returns null, then ownership of the memory
|
||||||
/// block has not been transferred to this allocator, and the
|
/// block has not been transferred to this allocator, and the
|
||||||
|
|
|
@ -10,7 +10,6 @@ use crate::mem;
|
||||||
use crate::num::flt2dec;
|
use crate::num::flt2dec;
|
||||||
use crate::ops::Deref;
|
use crate::ops::Deref;
|
||||||
use crate::result;
|
use crate::result;
|
||||||
use crate::slice;
|
|
||||||
use crate::str;
|
use crate::str;
|
||||||
|
|
||||||
mod builders;
|
mod builders;
|
||||||
|
@ -234,8 +233,6 @@ pub struct Formatter<'a> {
|
||||||
precision: Option<usize>,
|
precision: Option<usize>,
|
||||||
|
|
||||||
buf: &'a mut (dyn Write + 'a),
|
buf: &'a mut (dyn Write + 'a),
|
||||||
curarg: slice::Iter<'a, ArgumentV1<'a>>,
|
|
||||||
args: &'a [ArgumentV1<'a>],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NB. Argument is essentially an optimized partially applied formatting function,
|
// NB. Argument is essentially an optimized partially applied formatting function,
|
||||||
|
@ -1043,8 +1040,6 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
|
||||||
buf: output,
|
buf: output,
|
||||||
align: rt::v1::Alignment::Unknown,
|
align: rt::v1::Alignment::Unknown,
|
||||||
fill: ' ',
|
fill: ' ',
|
||||||
args: args.args,
|
|
||||||
curarg: args.args.iter(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut idx = 0;
|
let mut idx = 0;
|
||||||
|
@ -1063,7 +1058,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
|
||||||
// a string piece.
|
// a string piece.
|
||||||
for (arg, piece) in fmt.iter().zip(args.pieces.iter()) {
|
for (arg, piece) in fmt.iter().zip(args.pieces.iter()) {
|
||||||
formatter.buf.write_str(*piece)?;
|
formatter.buf.write_str(*piece)?;
|
||||||
formatter.run(arg)?;
|
run(&mut formatter, arg, &args.args)?;
|
||||||
idx += 1;
|
idx += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1077,6 +1072,39 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn run(fmt: &mut Formatter<'_>, arg: &rt::v1::Argument, args: &[ArgumentV1<'_>]) -> Result {
|
||||||
|
fmt.fill = arg.format.fill;
|
||||||
|
fmt.align = arg.format.align;
|
||||||
|
fmt.flags = arg.format.flags;
|
||||||
|
fmt.width = getcount(args, &arg.format.width);
|
||||||
|
fmt.precision = getcount(args, &arg.format.precision);
|
||||||
|
|
||||||
|
// Extract the correct argument
|
||||||
|
let value = {
|
||||||
|
#[cfg(bootstrap)]
|
||||||
|
{
|
||||||
|
match arg.position {
|
||||||
|
rt::v1::Position::At(i) => args[i],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
{
|
||||||
|
args[arg.position]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Then actually do some printing
|
||||||
|
(value.formatter)(value.value, fmt)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getcount(args: &[ArgumentV1<'_>], cnt: &rt::v1::Count) -> Option<usize> {
|
||||||
|
match *cnt {
|
||||||
|
rt::v1::Count::Is(n) => Some(n),
|
||||||
|
rt::v1::Count::Implied => None,
|
||||||
|
rt::v1::Count::Param(i) => args[i].as_usize(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Padding after the end of something. Returned by `Formatter::padding`.
|
/// Padding after the end of something. Returned by `Formatter::padding`.
|
||||||
#[must_use = "don't forget to write the post padding"]
|
#[must_use = "don't forget to write the post padding"]
|
||||||
struct PostPadding {
|
struct PostPadding {
|
||||||
|
@ -1114,41 +1142,6 @@ impl<'a> Formatter<'a> {
|
||||||
align: self.align,
|
align: self.align,
|
||||||
width: self.width,
|
width: self.width,
|
||||||
precision: self.precision,
|
precision: self.precision,
|
||||||
|
|
||||||
// These only exist in the struct for the `run` method,
|
|
||||||
// which won’t be used together with this method.
|
|
||||||
curarg: self.curarg.clone(),
|
|
||||||
args: self.args,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// First up is the collection of functions used to execute a format string
|
|
||||||
// at runtime. This consumes all of the compile-time statics generated by
|
|
||||||
// the format! syntax extension.
|
|
||||||
fn run(&mut self, arg: &rt::v1::Argument) -> Result {
|
|
||||||
// Fill in the format parameters into the formatter
|
|
||||||
self.fill = arg.format.fill;
|
|
||||||
self.align = arg.format.align;
|
|
||||||
self.flags = arg.format.flags;
|
|
||||||
self.width = self.getcount(&arg.format.width);
|
|
||||||
self.precision = self.getcount(&arg.format.precision);
|
|
||||||
|
|
||||||
// Extract the correct argument
|
|
||||||
let value = match arg.position {
|
|
||||||
rt::v1::Position::Next => *self.curarg.next().unwrap(),
|
|
||||||
rt::v1::Position::At(i) => self.args[i],
|
|
||||||
};
|
|
||||||
|
|
||||||
// Then actually do some printing
|
|
||||||
(value.formatter)(value.value, self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getcount(&mut self, cnt: &rt::v1::Count) -> Option<usize> {
|
|
||||||
match *cnt {
|
|
||||||
rt::v1::Count::Is(n) => Some(n),
|
|
||||||
rt::v1::Count::Implied => None,
|
|
||||||
rt::v1::Count::Param(i) => self.args[i].as_usize(),
|
|
||||||
rt::v1::Count::NextParam => self.curarg.next()?.as_usize(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,10 @@
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct Argument {
|
pub struct Argument {
|
||||||
|
#[cfg(bootstrap)]
|
||||||
pub position: Position,
|
pub position: Position,
|
||||||
|
#[cfg(not(bootstrap))]
|
||||||
|
pub position: usize,
|
||||||
pub format: FormatSpec,
|
pub format: FormatSpec,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,12 +40,11 @@ pub enum Alignment {
|
||||||
pub enum Count {
|
pub enum Count {
|
||||||
Is(usize),
|
Is(usize),
|
||||||
Param(usize),
|
Param(usize),
|
||||||
NextParam,
|
|
||||||
Implied,
|
Implied,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(bootstrap)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum Position {
|
pub enum Position {
|
||||||
Next,
|
|
||||||
At(usize),
|
At(usize),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
use crate::dep_graph::{DepConstructor, DepNode, WorkProduct, WorkProductId};
|
use crate::dep_graph::{DepConstructor, DepNode, WorkProduct, WorkProductId};
|
||||||
use crate::ich::{Fingerprint, NodeIdHashingMode, StableHashingContext};
|
use crate::ich::{Fingerprint, NodeIdHashingMode, StableHashingContext};
|
||||||
use crate::session::config::OptLevel;
|
use crate::session::config::OptLevel;
|
||||||
use crate::traits::TraitQueryMode;
|
|
||||||
use crate::ty::print::obsolete::DefPathBasedNames;
|
use crate::ty::print::obsolete::DefPathBasedNames;
|
||||||
use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt};
|
use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt};
|
||||||
use rustc_data_structures::base_n;
|
use rustc_data_structures::base_n;
|
||||||
|
@ -168,9 +167,7 @@ impl<'tcx> MonoItem<'tcx> {
|
||||||
MonoItem::GlobalAsm(..) => return true,
|
MonoItem::GlobalAsm(..) => return true,
|
||||||
};
|
};
|
||||||
|
|
||||||
// We shouldn't encounter any overflow here, so we use TraitQueryMode::Standard\
|
tcx.substitute_normalize_and_test_predicates((def_id, &substs))
|
||||||
// to report an error if overflow somehow occurs.
|
|
||||||
tcx.substitute_normalize_and_test_predicates((def_id, &substs, TraitQueryMode::Standard))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_string(&self, tcx: TyCtxt<'tcx>, debug: bool) -> String {
|
pub fn to_string(&self, tcx: TyCtxt<'tcx>, debug: bool) -> String {
|
||||||
|
|
|
@ -1156,11 +1156,11 @@ rustc_queries! {
|
||||||
desc { "normalizing `{:?}`", goal }
|
desc { "normalizing `{:?}`", goal }
|
||||||
}
|
}
|
||||||
|
|
||||||
query substitute_normalize_and_test_predicates(key: (DefId, SubstsRef<'tcx>, traits::TraitQueryMode)) -> bool {
|
query substitute_normalize_and_test_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool {
|
||||||
no_force
|
no_force
|
||||||
desc { |tcx|
|
desc { |tcx|
|
||||||
"testing substituted normalized predicates in mode {:?}:`{}`",
|
"testing substituted normalized predicates:`{}`",
|
||||||
key.2, tcx.def_path_str(key.0)
|
tcx.def_path_str(key.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ use super::CodeSelectionError;
|
||||||
use super::{ConstEvalFailure, Unimplemented};
|
use super::{ConstEvalFailure, Unimplemented};
|
||||||
use super::{FulfillmentError, FulfillmentErrorCode};
|
use super::{FulfillmentError, FulfillmentErrorCode};
|
||||||
use super::{ObligationCause, PredicateObligation};
|
use super::{ObligationCause, PredicateObligation};
|
||||||
use crate::traits::TraitQueryMode;
|
|
||||||
|
|
||||||
impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
|
impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
|
||||||
type Predicate = ty::Predicate<'tcx>;
|
type Predicate = ty::Predicate<'tcx>;
|
||||||
|
@ -63,9 +62,6 @@ pub struct FulfillmentContext<'tcx> {
|
||||||
// a snapshot (they don't *straddle* a snapshot, so there
|
// a snapshot (they don't *straddle* a snapshot, so there
|
||||||
// is no trouble there).
|
// is no trouble there).
|
||||||
usable_in_snapshot: bool,
|
usable_in_snapshot: bool,
|
||||||
|
|
||||||
// The `TraitQueryMode` used when constructing a `SelectionContext`
|
|
||||||
query_mode: TraitQueryMode,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -79,26 +75,12 @@ pub struct PendingPredicateObligation<'tcx> {
|
||||||
static_assert_size!(PendingPredicateObligation<'_>, 136);
|
static_assert_size!(PendingPredicateObligation<'_>, 136);
|
||||||
|
|
||||||
impl<'a, 'tcx> FulfillmentContext<'tcx> {
|
impl<'a, 'tcx> FulfillmentContext<'tcx> {
|
||||||
/// Creates a new fulfillment context with `TraitQueryMode::Standard`
|
/// Creates a new fulfillment context.
|
||||||
/// You almost always want to use this instead of `with_query_mode`
|
|
||||||
pub fn new() -> FulfillmentContext<'tcx> {
|
pub fn new() -> FulfillmentContext<'tcx> {
|
||||||
FulfillmentContext {
|
FulfillmentContext {
|
||||||
predicates: ObligationForest::new(),
|
predicates: ObligationForest::new(),
|
||||||
register_region_obligations: true,
|
register_region_obligations: true,
|
||||||
usable_in_snapshot: false,
|
usable_in_snapshot: false,
|
||||||
query_mode: TraitQueryMode::Standard,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates a new fulfillment context with the specified query mode.
|
|
||||||
/// This should only be used when you want to ignore overflow,
|
|
||||||
/// rather than reporting it as an error.
|
|
||||||
pub fn with_query_mode(query_mode: TraitQueryMode) -> FulfillmentContext<'tcx> {
|
|
||||||
FulfillmentContext {
|
|
||||||
predicates: ObligationForest::new(),
|
|
||||||
register_region_obligations: true,
|
|
||||||
usable_in_snapshot: false,
|
|
||||||
query_mode,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +89,6 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
|
||||||
predicates: ObligationForest::new(),
|
predicates: ObligationForest::new(),
|
||||||
register_region_obligations: true,
|
register_region_obligations: true,
|
||||||
usable_in_snapshot: true,
|
usable_in_snapshot: true,
|
||||||
query_mode: TraitQueryMode::Standard,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +97,6 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
|
||||||
predicates: ObligationForest::new(),
|
predicates: ObligationForest::new(),
|
||||||
register_region_obligations: false,
|
register_region_obligations: false,
|
||||||
usable_in_snapshot: false,
|
usable_in_snapshot: false,
|
||||||
query_mode: TraitQueryMode::Standard,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,7 +217,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
infcx: &InferCtxt<'_, 'tcx>,
|
infcx: &InferCtxt<'_, 'tcx>,
|
||||||
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
|
) -> Result<(), Vec<FulfillmentError<'tcx>>> {
|
||||||
let mut selcx = SelectionContext::with_query_mode(infcx, self.query_mode);
|
let mut selcx = SelectionContext::new(infcx);
|
||||||
self.select(&mut selcx)
|
self.select(&mut selcx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ pub enum IntercrateMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The mode that trait queries run in.
|
/// The mode that trait queries run in.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, HashStable)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||||
pub enum TraitQueryMode {
|
pub enum TraitQueryMode {
|
||||||
// Standard/un-canonicalized queries get accurate
|
// Standard/un-canonicalized queries get accurate
|
||||||
// spans etc. passed in and hence can do reasonable
|
// spans etc. passed in and hence can do reasonable
|
||||||
|
@ -1014,17 +1014,16 @@ where
|
||||||
/// environment. If this returns false, then either normalize
|
/// environment. If this returns false, then either normalize
|
||||||
/// encountered an error or one of the predicates did not hold. Used
|
/// encountered an error or one of the predicates did not hold. Used
|
||||||
/// when creating vtables to check for unsatisfiable methods.
|
/// when creating vtables to check for unsatisfiable methods.
|
||||||
fn normalize_and_test_predicates<'tcx>(
|
pub fn normalize_and_test_predicates<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
predicates: Vec<ty::Predicate<'tcx>>,
|
predicates: Vec<ty::Predicate<'tcx>>,
|
||||||
mode: TraitQueryMode,
|
|
||||||
) -> bool {
|
) -> bool {
|
||||||
debug!("normalize_and_test_predicates(predicates={:?}, mode={:?})", predicates, mode);
|
debug!("normalize_and_test_predicates(predicates={:?})", predicates);
|
||||||
|
|
||||||
let result = tcx.infer_ctxt().enter(|infcx| {
|
let result = tcx.infer_ctxt().enter(|infcx| {
|
||||||
let param_env = ty::ParamEnv::reveal_all();
|
let param_env = ty::ParamEnv::reveal_all();
|
||||||
let mut selcx = SelectionContext::with_query_mode(&infcx, mode);
|
let mut selcx = SelectionContext::new(&infcx);
|
||||||
let mut fulfill_cx = FulfillmentContext::with_query_mode(mode);
|
let mut fulfill_cx = FulfillmentContext::new();
|
||||||
let cause = ObligationCause::dummy();
|
let cause = ObligationCause::dummy();
|
||||||
let Normalized { value: predicates, obligations } =
|
let Normalized { value: predicates, obligations } =
|
||||||
normalize(&mut selcx, param_env, cause.clone(), &predicates);
|
normalize(&mut selcx, param_env, cause.clone(), &predicates);
|
||||||
|
@ -1044,12 +1043,12 @@ fn normalize_and_test_predicates<'tcx>(
|
||||||
|
|
||||||
fn substitute_normalize_and_test_predicates<'tcx>(
|
fn substitute_normalize_and_test_predicates<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
key: (DefId, SubstsRef<'tcx>, TraitQueryMode),
|
key: (DefId, SubstsRef<'tcx>),
|
||||||
) -> bool {
|
) -> bool {
|
||||||
debug!("substitute_normalize_and_test_predicates(key={:?})", key);
|
debug!("substitute_normalize_and_test_predicates(key={:?})", key);
|
||||||
|
|
||||||
let predicates = tcx.predicates_of(key.0).instantiate(tcx, key.1).predicates;
|
let predicates = tcx.predicates_of(key.0).instantiate(tcx, key.1).predicates;
|
||||||
let result = normalize_and_test_predicates(tcx, predicates, key.2);
|
let result = normalize_and_test_predicates(tcx, predicates);
|
||||||
|
|
||||||
debug!("substitute_normalize_and_test_predicates(key={:?}) = {:?}", key, result);
|
debug!("substitute_normalize_and_test_predicates(key={:?}) = {:?}", key, result);
|
||||||
result
|
result
|
||||||
|
@ -1102,10 +1101,7 @@ fn vtable_methods<'tcx>(
|
||||||
// Note that this method could then never be called, so we
|
// Note that this method could then never be called, so we
|
||||||
// do not want to try and codegen it, in that case (see #23435).
|
// do not want to try and codegen it, in that case (see #23435).
|
||||||
let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
|
let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
|
||||||
// We don't expect overflow here, so report an error if it somehow ends
|
if !normalize_and_test_predicates(tcx, predicates.predicates) {
|
||||||
// up happening.
|
|
||||||
if !normalize_and_test_predicates(tcx, predicates.predicates, TraitQueryMode::Standard)
|
|
||||||
{
|
|
||||||
debug!("vtable_methods: predicates do not hold");
|
debug!("vtable_methods: predicates do not hold");
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,7 +141,12 @@ impl<'tcx> InstanceDef<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
|
pub fn requires_caller_location(&self, tcx: TyCtxt<'_>) -> bool {
|
||||||
tcx.codegen_fn_attrs(self.def_id()).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
|
match *self {
|
||||||
|
InstanceDef::Item(def_id) => {
|
||||||
|
tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER)
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,15 +125,6 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Key for (DefId, SubstsRef<'tcx>, traits::TraitQueryMode) {
|
|
||||||
fn query_crate(&self) -> CrateNum {
|
|
||||||
self.0.krate
|
|
||||||
}
|
|
||||||
fn default_span(&self, tcx: TyCtxt<'_>) -> Span {
|
|
||||||
self.0.default_span(tcx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
|
impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) {
|
||||||
fn query_crate(&self) -> CrateNum {
|
fn query_crate(&self) -> CrateNum {
|
||||||
self.1.def_id().krate
|
self.1.def_id().krate
|
||||||
|
|
|
@ -590,17 +590,6 @@ impl<'a, 'b> Context<'a, 'b> {
|
||||||
parse::NextArgument(ref arg) => {
|
parse::NextArgument(ref arg) => {
|
||||||
// Build the position
|
// Build the position
|
||||||
let pos = {
|
let pos = {
|
||||||
let pos = |c, arg| {
|
|
||||||
let mut path = Context::rtpath(self.ecx, "Position");
|
|
||||||
path.push(self.ecx.ident_of(c, sp));
|
|
||||||
match arg {
|
|
||||||
Some(i) => {
|
|
||||||
let arg = self.ecx.expr_usize(sp, i);
|
|
||||||
self.ecx.expr_call_global(sp, path, vec![arg])
|
|
||||||
}
|
|
||||||
None => self.ecx.expr_path(self.ecx.path_global(sp, path)),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
match arg.position {
|
match arg.position {
|
||||||
parse::ArgumentIs(i) | parse::ArgumentImplicitlyIs(i) => {
|
parse::ArgumentIs(i) | parse::ArgumentImplicitlyIs(i) => {
|
||||||
// Map to index in final generated argument array
|
// Map to index in final generated argument array
|
||||||
|
@ -615,7 +604,7 @@ impl<'a, 'b> Context<'a, 'b> {
|
||||||
arg_idx
|
arg_idx
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
pos("At", Some(arg_idx))
|
self.ecx.expr_usize(sp, arg_idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// should never be the case, because names are already
|
// should never be the case, because names are already
|
||||||
|
|
|
@ -31,9 +31,13 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
|
||||||
|
|
||||||
let mut result = match instance {
|
let mut result = match instance {
|
||||||
ty::InstanceDef::Item(..) => bug!("item {:?} passed to make_shim", instance),
|
ty::InstanceDef::Item(..) => bug!("item {:?} passed to make_shim", instance),
|
||||||
ty::InstanceDef::VtableShim(def_id) => {
|
ty::InstanceDef::VtableShim(def_id) => build_call_shim(
|
||||||
build_call_shim(tcx, instance, Adjustment::DerefMove, CallKind::Direct(def_id), None)
|
tcx,
|
||||||
}
|
instance,
|
||||||
|
Some(Adjustment::DerefMove),
|
||||||
|
CallKind::Direct(def_id),
|
||||||
|
None,
|
||||||
|
),
|
||||||
ty::InstanceDef::FnPtrShim(def_id, ty) => {
|
ty::InstanceDef::FnPtrShim(def_id, ty) => {
|
||||||
let trait_ = tcx.trait_of_item(def_id).unwrap();
|
let trait_ = tcx.trait_of_item(def_id).unwrap();
|
||||||
let adjustment = match tcx.lang_items().fn_trait_kind(trait_) {
|
let adjustment = match tcx.lang_items().fn_trait_kind(trait_) {
|
||||||
|
@ -50,7 +54,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
|
||||||
let sig = tcx.erase_late_bound_regions(&ty.fn_sig(tcx));
|
let sig = tcx.erase_late_bound_regions(&ty.fn_sig(tcx));
|
||||||
let arg_tys = sig.inputs();
|
let arg_tys = sig.inputs();
|
||||||
|
|
||||||
build_call_shim(tcx, instance, adjustment, CallKind::Indirect, Some(arg_tys))
|
build_call_shim(tcx, instance, Some(adjustment), CallKind::Indirect, Some(arg_tys))
|
||||||
}
|
}
|
||||||
// We are generating a call back to our def-id, which the
|
// We are generating a call back to our def-id, which the
|
||||||
// codegen backend knows to turn to an actual call, be it
|
// codegen backend knows to turn to an actual call, be it
|
||||||
|
@ -58,7 +62,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
|
||||||
// indirect calls must be codegen'd differently than direct ones
|
// indirect calls must be codegen'd differently than direct ones
|
||||||
// (such as `#[track_caller]`).
|
// (such as `#[track_caller]`).
|
||||||
ty::InstanceDef::ReifyShim(def_id) => {
|
ty::InstanceDef::ReifyShim(def_id) => {
|
||||||
build_call_shim(tcx, instance, Adjustment::Identity, CallKind::Direct(def_id), None)
|
build_call_shim(tcx, instance, None, CallKind::Direct(def_id), None)
|
||||||
}
|
}
|
||||||
ty::InstanceDef::ClosureOnceShim { call_once: _ } => {
|
ty::InstanceDef::ClosureOnceShim { call_once: _ } => {
|
||||||
let fn_mut = tcx.lang_items().fn_mut_trait().unwrap();
|
let fn_mut = tcx.lang_items().fn_mut_trait().unwrap();
|
||||||
|
@ -68,7 +72,13 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.def_id;
|
.def_id;
|
||||||
|
|
||||||
build_call_shim(tcx, instance, Adjustment::RefMut, CallKind::Direct(call_mut), None)
|
build_call_shim(
|
||||||
|
tcx,
|
||||||
|
instance,
|
||||||
|
Some(Adjustment::RefMut),
|
||||||
|
CallKind::Direct(call_mut),
|
||||||
|
None,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
ty::InstanceDef::DropGlue(def_id, ty) => build_drop_shim(tcx, def_id, ty),
|
ty::InstanceDef::DropGlue(def_id, ty) => build_drop_shim(tcx, def_id, ty),
|
||||||
ty::InstanceDef::CloneShim(def_id, ty) => {
|
ty::InstanceDef::CloneShim(def_id, ty) => {
|
||||||
|
@ -648,7 +658,7 @@ impl CloneShimBuilder<'tcx> {
|
||||||
fn build_call_shim<'tcx>(
|
fn build_call_shim<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
instance: ty::InstanceDef<'tcx>,
|
instance: ty::InstanceDef<'tcx>,
|
||||||
rcvr_adjustment: Adjustment,
|
rcvr_adjustment: Option<Adjustment>,
|
||||||
call_kind: CallKind,
|
call_kind: CallKind,
|
||||||
untuple_args: Option<&[Ty<'tcx>]>,
|
untuple_args: Option<&[Ty<'tcx>]>,
|
||||||
) -> BodyAndCache<'tcx> {
|
) -> BodyAndCache<'tcx> {
|
||||||
|
@ -680,14 +690,16 @@ fn build_call_shim<'tcx>(
|
||||||
let mut local_decls = local_decls_for_sig(&sig, span);
|
let mut local_decls = local_decls_for_sig(&sig, span);
|
||||||
let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
|
let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
|
||||||
|
|
||||||
let rcvr_arg = Local::new(1 + 0);
|
let rcvr_place = || {
|
||||||
let rcvr_l = Place::from(rcvr_arg);
|
assert!(rcvr_adjustment.is_some());
|
||||||
|
Place::from(Local::new(1 + 0))
|
||||||
|
};
|
||||||
let mut statements = vec![];
|
let mut statements = vec![];
|
||||||
|
|
||||||
let rcvr = match rcvr_adjustment {
|
let rcvr = rcvr_adjustment.map(|rcvr_adjustment| match rcvr_adjustment {
|
||||||
Adjustment::Identity => Operand::Move(rcvr_l),
|
Adjustment::Identity => Operand::Move(rcvr_place()),
|
||||||
Adjustment::Deref => Operand::Copy(tcx.mk_place_deref(rcvr_l)),
|
Adjustment::Deref => Operand::Copy(tcx.mk_place_deref(rcvr_place())),
|
||||||
Adjustment::DerefMove => Operand::Move(tcx.mk_place_deref(rcvr_l)),
|
Adjustment::DerefMove => Operand::Move(tcx.mk_place_deref(rcvr_place())),
|
||||||
Adjustment::RefMut => {
|
Adjustment::RefMut => {
|
||||||
// let rcvr = &mut rcvr;
|
// let rcvr = &mut rcvr;
|
||||||
let ref_rcvr = local_decls.push(temp_decl(
|
let ref_rcvr = local_decls.push(temp_decl(
|
||||||
|
@ -703,15 +715,15 @@ fn build_call_shim<'tcx>(
|
||||||
source_info,
|
source_info,
|
||||||
kind: StatementKind::Assign(box (
|
kind: StatementKind::Assign(box (
|
||||||
Place::from(ref_rcvr),
|
Place::from(ref_rcvr),
|
||||||
Rvalue::Ref(tcx.lifetimes.re_erased, borrow_kind, rcvr_l),
|
Rvalue::Ref(tcx.lifetimes.re_erased, borrow_kind, rcvr_place()),
|
||||||
)),
|
)),
|
||||||
});
|
});
|
||||||
Operand::Move(Place::from(ref_rcvr))
|
Operand::Move(Place::from(ref_rcvr))
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
let (callee, mut args) = match call_kind {
|
let (callee, mut args) = match call_kind {
|
||||||
CallKind::Indirect => (rcvr, vec![]),
|
CallKind::Indirect => (rcvr.unwrap(), vec![]),
|
||||||
CallKind::Direct(def_id) => {
|
CallKind::Direct(def_id) => {
|
||||||
let ty = tcx.type_of(def_id);
|
let ty = tcx.type_of(def_id);
|
||||||
(
|
(
|
||||||
|
@ -720,21 +732,35 @@ fn build_call_shim<'tcx>(
|
||||||
user_ty: None,
|
user_ty: None,
|
||||||
literal: ty::Const::zero_sized(tcx, ty),
|
literal: ty::Const::zero_sized(tcx, ty),
|
||||||
}),
|
}),
|
||||||
vec![rcvr],
|
rcvr.into_iter().collect::<Vec<_>>(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(untuple_args) = untuple_args {
|
let mut arg_range = 0..sig.inputs().len();
|
||||||
args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
|
|
||||||
let arg_place = Place::from(Local::new(1 + 1));
|
// Take the `self` ("receiver") argument out of the range (it's adjusted above).
|
||||||
Operand::Move(tcx.mk_place_field(arg_place, Field::new(i), *ity))
|
if rcvr_adjustment.is_some() {
|
||||||
}));
|
arg_range.start += 1;
|
||||||
} else {
|
|
||||||
args.extend((1..sig.inputs().len()).map(|i| Operand::Move(Place::from(Local::new(1 + i)))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let n_blocks = if let Adjustment::RefMut = rcvr_adjustment { 5 } else { 2 };
|
// Take the last argument, if we need to untuple it (handled below).
|
||||||
|
if untuple_args.is_some() {
|
||||||
|
arg_range.end -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass all of the non-special arguments directly.
|
||||||
|
args.extend(arg_range.map(|i| Operand::Move(Place::from(Local::new(1 + i)))));
|
||||||
|
|
||||||
|
// Untuple the last argument, if we have to.
|
||||||
|
if let Some(untuple_args) = untuple_args {
|
||||||
|
let tuple_arg = Local::new(1 + (sig.inputs().len() - 1));
|
||||||
|
args.extend(untuple_args.iter().enumerate().map(|(i, ity)| {
|
||||||
|
Operand::Move(tcx.mk_place_field(Place::from(tuple_arg), Field::new(i), *ity))
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
let n_blocks = if let Some(Adjustment::RefMut) = rcvr_adjustment { 5 } else { 2 };
|
||||||
let mut blocks = IndexVec::with_capacity(n_blocks);
|
let mut blocks = IndexVec::with_capacity(n_blocks);
|
||||||
let block = |blocks: &mut IndexVec<_, _>, statements, kind, is_cleanup| {
|
let block = |blocks: &mut IndexVec<_, _>, statements, kind, is_cleanup| {
|
||||||
blocks.push(BasicBlockData {
|
blocks.push(BasicBlockData {
|
||||||
|
@ -752,7 +778,7 @@ fn build_call_shim<'tcx>(
|
||||||
func: callee,
|
func: callee,
|
||||||
args,
|
args,
|
||||||
destination: Some((Place::return_place(), BasicBlock::new(1))),
|
destination: Some((Place::return_place(), BasicBlock::new(1))),
|
||||||
cleanup: if let Adjustment::RefMut = rcvr_adjustment {
|
cleanup: if let Some(Adjustment::RefMut) = rcvr_adjustment {
|
||||||
Some(BasicBlock::new(3))
|
Some(BasicBlock::new(3))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -762,13 +788,13 @@ fn build_call_shim<'tcx>(
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Adjustment::RefMut = rcvr_adjustment {
|
if let Some(Adjustment::RefMut) = rcvr_adjustment {
|
||||||
// BB #1 - drop for Self
|
// BB #1 - drop for Self
|
||||||
block(
|
block(
|
||||||
&mut blocks,
|
&mut blocks,
|
||||||
vec![],
|
vec![],
|
||||||
TerminatorKind::Drop {
|
TerminatorKind::Drop {
|
||||||
location: Place::from(rcvr_arg),
|
location: rcvr_place(),
|
||||||
target: BasicBlock::new(2),
|
target: BasicBlock::new(2),
|
||||||
unwind: None,
|
unwind: None,
|
||||||
},
|
},
|
||||||
|
@ -777,13 +803,13 @@ fn build_call_shim<'tcx>(
|
||||||
}
|
}
|
||||||
// BB #1/#2 - return
|
// BB #1/#2 - return
|
||||||
block(&mut blocks, vec![], TerminatorKind::Return, false);
|
block(&mut blocks, vec![], TerminatorKind::Return, false);
|
||||||
if let Adjustment::RefMut = rcvr_adjustment {
|
if let Some(Adjustment::RefMut) = rcvr_adjustment {
|
||||||
// BB #3 - drop if closure panics
|
// BB #3 - drop if closure panics
|
||||||
block(
|
block(
|
||||||
&mut blocks,
|
&mut blocks,
|
||||||
vec![],
|
vec![],
|
||||||
TerminatorKind::Drop {
|
TerminatorKind::Drop {
|
||||||
location: Place::from(rcvr_arg),
|
location: rcvr_place(),
|
||||||
target: BasicBlock::new(4),
|
target: BasicBlock::new(4),
|
||||||
unwind: None,
|
unwind: None,
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,7 +14,7 @@ use rustc::mir::{
|
||||||
SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind,
|
SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind,
|
||||||
UnOp, RETURN_PLACE,
|
UnOp, RETURN_PLACE,
|
||||||
};
|
};
|
||||||
use rustc::traits::TraitQueryMode;
|
use rustc::traits;
|
||||||
use rustc::ty::layout::{
|
use rustc::ty::layout::{
|
||||||
HasDataLayout, HasTyCtxt, LayoutError, LayoutOf, Size, TargetDataLayout, TyLayout,
|
HasDataLayout, HasTyCtxt, LayoutError, LayoutOf, Size, TargetDataLayout, TyLayout,
|
||||||
};
|
};
|
||||||
|
@ -90,28 +90,28 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
|
||||||
// If there are unsatisfiable where clauses, then all bets are
|
// If there are unsatisfiable where clauses, then all bets are
|
||||||
// off, and we just give up.
|
// off, and we just give up.
|
||||||
//
|
//
|
||||||
// Note that we use TraitQueryMode::Canonical here, which causes
|
// We manually filter the predicates, skipping anything that's not
|
||||||
// us to treat overflow like any other error. This is because we
|
// "global". We are in a potentially generic context
|
||||||
// are "speculatively" evaluating this item with the default substs.
|
// (e.g. we are evaluating a function without substituting generic
|
||||||
// While this usually succeeds, it may fail with tricky impls
|
// parameters, so this filtering serves two purposes:
|
||||||
// (e.g. the typenum crate). Const-propagation is fundamentally
|
|
||||||
// "best-effort", and does not affect correctness in any way.
|
|
||||||
// Therefore, it's perfectly fine to just "give up" if we're
|
|
||||||
// unable to check the bounds with the default substs.
|
|
||||||
//
|
//
|
||||||
// False negatives (failing to run const-prop on something when we actually
|
// 1. We skip evaluating any predicates that we would
|
||||||
// could) are fine. However, false positives (running const-prop on
|
// never be able prove are unsatisfiable (e.g. `<T as Foo>`
|
||||||
// an item with unsatisfiable bounds) can lead to us generating invalid
|
// 2. We avoid trying to normalize predicates involving generic
|
||||||
// MIR.
|
// parameters (e.g. `<T as Foo>::MyItem`). This can confuse
|
||||||
if !tcx.substitute_normalize_and_test_predicates((
|
// the normalization code (leading to cycle errors), since
|
||||||
source.def_id(),
|
// it's usually never invoked in this way.
|
||||||
InternalSubsts::identity_for_item(tcx, source.def_id()),
|
let predicates = tcx
|
||||||
TraitQueryMode::Canonical,
|
.predicates_of(source.def_id())
|
||||||
)) {
|
.predicates
|
||||||
trace!(
|
.iter()
|
||||||
"ConstProp skipped for item with unsatisfiable predicates: {:?}",
|
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None })
|
||||||
source.def_id()
|
.collect();
|
||||||
);
|
if !traits::normalize_and_test_predicates(
|
||||||
|
tcx,
|
||||||
|
traits::elaborate_predicates(tcx, predicates).collect(),
|
||||||
|
) {
|
||||||
|
trace!("ConstProp skipped for {:?}: found unsatisfiable predicates", source.def_id());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2321,8 +2321,8 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
|
||||||
"{}{}{}{}{:#}fn {}{:#}",
|
"{}{}{}{}{:#}fn {}{:#}",
|
||||||
it.visibility.print_with_space(),
|
it.visibility.print_with_space(),
|
||||||
f.header.constness.print_with_space(),
|
f.header.constness.print_with_space(),
|
||||||
f.header.unsafety.print_with_space(),
|
|
||||||
f.header.asyncness.print_with_space(),
|
f.header.asyncness.print_with_space(),
|
||||||
|
f.header.unsafety.print_with_space(),
|
||||||
print_abi_with_space(f.header.abi),
|
print_abi_with_space(f.header.abi),
|
||||||
it.name.as_ref().unwrap(),
|
it.name.as_ref().unwrap(),
|
||||||
f.generics.print()
|
f.generics.print()
|
||||||
|
@ -2332,12 +2332,12 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
|
||||||
render_attributes(w, it, false);
|
render_attributes(w, it, false);
|
||||||
write!(
|
write!(
|
||||||
w,
|
w,
|
||||||
"{vis}{constness}{unsafety}{asyncness}{abi}fn \
|
"{vis}{constness}{asyncness}{unsafety}{abi}fn \
|
||||||
{name}{generics}{decl}{where_clause}</pre>",
|
{name}{generics}{decl}{where_clause}</pre>",
|
||||||
vis = it.visibility.print_with_space(),
|
vis = it.visibility.print_with_space(),
|
||||||
constness = f.header.constness.print_with_space(),
|
constness = f.header.constness.print_with_space(),
|
||||||
unsafety = f.header.unsafety.print_with_space(),
|
|
||||||
asyncness = f.header.asyncness.print_with_space(),
|
asyncness = f.header.asyncness.print_with_space(),
|
||||||
|
unsafety = f.header.unsafety.print_with_space(),
|
||||||
abi = print_abi_with_space(f.header.abi),
|
abi = print_abi_with_space(f.header.abi),
|
||||||
name = it.name.as_ref().unwrap(),
|
name = it.name.as_ref().unwrap(),
|
||||||
generics = f.generics.print(),
|
generics = f.generics.print(),
|
||||||
|
@ -2832,8 +2832,8 @@ fn render_assoc_item(
|
||||||
"{}{}{}{}{}{:#}fn {}{:#}",
|
"{}{}{}{}{}{:#}fn {}{:#}",
|
||||||
meth.visibility.print_with_space(),
|
meth.visibility.print_with_space(),
|
||||||
header.constness.print_with_space(),
|
header.constness.print_with_space(),
|
||||||
header.unsafety.print_with_space(),
|
|
||||||
header.asyncness.print_with_space(),
|
header.asyncness.print_with_space(),
|
||||||
|
header.unsafety.print_with_space(),
|
||||||
print_default_space(meth.is_default()),
|
print_default_space(meth.is_default()),
|
||||||
print_abi_with_space(header.abi),
|
print_abi_with_space(header.abi),
|
||||||
name,
|
name,
|
||||||
|
@ -2854,8 +2854,8 @@ fn render_assoc_item(
|
||||||
if parent == ItemType::Trait { " " } else { "" },
|
if parent == ItemType::Trait { " " } else { "" },
|
||||||
meth.visibility.print_with_space(),
|
meth.visibility.print_with_space(),
|
||||||
header.constness.print_with_space(),
|
header.constness.print_with_space(),
|
||||||
header.unsafety.print_with_space(),
|
|
||||||
header.asyncness.print_with_space(),
|
header.asyncness.print_with_space(),
|
||||||
|
header.unsafety.print_with_space(),
|
||||||
print_default_space(meth.is_default()),
|
print_default_space(meth.is_default()),
|
||||||
print_abi_with_space(header.abi),
|
print_abi_with_space(header.abi),
|
||||||
href = href,
|
href = href,
|
||||||
|
|
|
@ -15,6 +15,11 @@ pub async fn baz<T>(a: T) -> T {
|
||||||
a
|
a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @has async_fn/fn.qux.html '//pre[@class="rust fn"]' 'pub async unsafe fn qux() -> char'
|
||||||
|
pub async unsafe fn qux() -> char {
|
||||||
|
'⚠'
|
||||||
|
}
|
||||||
|
|
||||||
trait Bar {}
|
trait Bar {}
|
||||||
|
|
||||||
impl Bar for () {}
|
impl Bar for () {}
|
||||||
|
@ -26,8 +31,10 @@ pub async fn quux() -> impl Bar {
|
||||||
|
|
||||||
// @has async_fn/struct.Foo.html
|
// @has async_fn/struct.Foo.html
|
||||||
// @matches - '//code' 'pub async fn f\(\)$'
|
// @matches - '//code' 'pub async fn f\(\)$'
|
||||||
|
// @matches - '//code' 'pub async unsafe fn g\(\)$'
|
||||||
pub struct Foo;
|
pub struct Foo;
|
||||||
|
|
||||||
impl Foo {
|
impl Foo {
|
||||||
pub async fn f() {}
|
pub async fn f() {}
|
||||||
|
pub async unsafe fn g() {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,15 @@
|
||||||
// edition:2018
|
// edition:2018
|
||||||
// compile-flags: --crate-type lib
|
// compile-flags: --crate-type lib
|
||||||
|
|
||||||
use std::{
|
use std::{cell::RefCell, fmt::Debug, rc::Rc};
|
||||||
cell::RefCell,
|
|
||||||
fmt::Debug,
|
|
||||||
rc::Rc,
|
|
||||||
};
|
|
||||||
|
|
||||||
fn non_sync() -> impl Debug { RefCell::new(()) }
|
fn non_sync() -> impl Debug {
|
||||||
|
RefCell::new(())
|
||||||
|
}
|
||||||
|
|
||||||
fn non_send() -> impl Debug { Rc::new(()) }
|
fn non_send() -> impl Debug {
|
||||||
|
Rc::new(())
|
||||||
|
}
|
||||||
|
|
||||||
fn take_ref<T>(_: &T) {}
|
fn take_ref<T>(_: &T) {}
|
||||||
|
|
||||||
|
@ -53,5 +53,4 @@ pub fn pass_assert() {
|
||||||
//~^ ERROR future cannot be sent between threads safely
|
//~^ ERROR future cannot be sent between threads safely
|
||||||
assert_send(non_sync_with_method_call());
|
assert_send(non_sync_with_method_call());
|
||||||
//~^ ERROR future cannot be sent between threads safely
|
//~^ ERROR future cannot be sent between threads safely
|
||||||
//~^^ ERROR future cannot be sent between threads safely
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,27 +62,5 @@ LL | }
|
||||||
LL | }
|
LL | }
|
||||||
| - `f` is later dropped here
|
| - `f` is later dropped here
|
||||||
|
|
||||||
error: future cannot be sent between threads safely
|
error: aborting due to 3 previous errors
|
||||||
--> $DIR/async-fn-nonsend.rs:54:5
|
|
||||||
|
|
|
||||||
LL | fn assert_send(_: impl Send) {}
|
|
||||||
| ----------- ---- required by this bound in `assert_send`
|
|
||||||
...
|
|
||||||
LL | assert_send(non_sync_with_method_call());
|
|
||||||
| ^^^^^^^^^^^ future returned by `non_sync_with_method_call` is not `Send`
|
|
||||||
|
|
|
||||||
= help: within `std::fmt::ArgumentV1<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)`
|
|
||||||
note: future is not `Send` as this value is used across an await
|
|
||||||
--> $DIR/async-fn-nonsend.rs:43:9
|
|
||||||
|
|
|
||||||
LL | let f: &mut std::fmt::Formatter = panic!();
|
|
||||||
| - has type `&mut std::fmt::Formatter<'_>`
|
|
||||||
LL | if non_sync().fmt(f).unwrap() == () {
|
|
||||||
LL | fut().await;
|
|
||||||
| ^^^^^^^^^^^ await occurs here, with `f` maybe used later
|
|
||||||
LL | }
|
|
||||||
LL | }
|
|
||||||
| - `f` is later dropped here
|
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// build-pass
|
// build-pass
|
||||||
|
// ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors)
|
||||||
|
|
||||||
#![warn(const_err)]
|
#![warn(const_err)]
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
warning: index out of bounds: the len is 3 but the index is 4
|
warning: index out of bounds: the len is 3 but the index is 4
|
||||||
--> $DIR/array-literal-index-oob.rs:6:8
|
--> $DIR/array-literal-index-oob.rs:7:8
|
||||||
|
|
|
|
||||||
LL | &{ [1, 2, 3][4] };
|
LL | &{ [1, 2, 3][4] };
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: lint level defined here
|
note: lint level defined here
|
||||||
--> $DIR/array-literal-index-oob.rs:3:9
|
--> $DIR/array-literal-index-oob.rs:4:9
|
||||||
|
|
|
|
||||||
LL | #![warn(const_err)]
|
LL | #![warn(const_err)]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
warning: reaching this expression at runtime will panic or abort
|
warning: reaching this expression at runtime will panic or abort
|
||||||
--> $DIR/array-literal-index-oob.rs:6:8
|
--> $DIR/array-literal-index-oob.rs:7:8
|
||||||
|
|
|
|
||||||
LL | &{ [1, 2, 3][4] };
|
LL | &{ [1, 2, 3][4] };
|
||||||
| ---^^^^^^^^^^^^--
|
| ---^^^^^^^^^^^^--
|
||||||
|
@ -19,7 +19,7 @@ LL | &{ [1, 2, 3][4] };
|
||||||
| indexing out of bounds: the len is 3 but the index is 4
|
| indexing out of bounds: the len is 3 but the index is 4
|
||||||
|
|
||||||
warning: erroneous constant used
|
warning: erroneous constant used
|
||||||
--> $DIR/array-literal-index-oob.rs:6:5
|
--> $DIR/array-literal-index-oob.rs:7:5
|
||||||
|
|
|
|
||||||
LL | &{ [1, 2, 3][4] };
|
LL | &{ [1, 2, 3][4] };
|
||||||
| ^^^^^^^^^^^^^^^^^ referenced constant has errors
|
| ^^^^^^^^^^^^^^^^^ referenced constant has errors
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// build-pass
|
// build-pass
|
||||||
|
// ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors)
|
||||||
// compile-flags: -O
|
// compile-flags: -O
|
||||||
|
|
||||||
#![warn(const_err)]
|
#![warn(const_err)]
|
||||||
|
|
|
@ -1,59 +1,59 @@
|
||||||
warning: this expression will panic at runtime
|
warning: this expression will panic at runtime
|
||||||
--> $DIR/promoted_errors.rs:8:14
|
--> $DIR/promoted_errors.rs:9:14
|
||||||
|
|
|
|
||||||
LL | let _x = 0u32 - 1;
|
LL | let _x = 0u32 - 1;
|
||||||
| ^^^^^^^^ attempt to subtract with overflow
|
| ^^^^^^^^ attempt to subtract with overflow
|
||||||
|
|
|
|
||||||
note: lint level defined here
|
note: lint level defined here
|
||||||
--> $DIR/promoted_errors.rs:4:9
|
--> $DIR/promoted_errors.rs:5:9
|
||||||
|
|
|
|
||||||
LL | #![warn(const_err)]
|
LL | #![warn(const_err)]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
warning: attempt to divide by zero
|
warning: attempt to divide by zero
|
||||||
--> $DIR/promoted_errors.rs:10:20
|
--> $DIR/promoted_errors.rs:11:20
|
||||||
|
|
|
|
||||||
LL | println!("{}", 1 / (1 - 1));
|
LL | println!("{}", 1 / (1 - 1));
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
warning: reaching this expression at runtime will panic or abort
|
warning: reaching this expression at runtime will panic or abort
|
||||||
--> $DIR/promoted_errors.rs:10:20
|
--> $DIR/promoted_errors.rs:11:20
|
||||||
|
|
|
|
||||||
LL | println!("{}", 1 / (1 - 1));
|
LL | println!("{}", 1 / (1 - 1));
|
||||||
| ^^^^^^^^^^^ dividing by zero
|
| ^^^^^^^^^^^ dividing by zero
|
||||||
|
|
||||||
warning: erroneous constant used
|
warning: erroneous constant used
|
||||||
--> $DIR/promoted_errors.rs:10:20
|
--> $DIR/promoted_errors.rs:11:20
|
||||||
|
|
|
|
||||||
LL | println!("{}", 1 / (1 - 1));
|
LL | println!("{}", 1 / (1 - 1));
|
||||||
| ^^^^^^^^^^^ referenced constant has errors
|
| ^^^^^^^^^^^ referenced constant has errors
|
||||||
|
|
||||||
warning: attempt to divide by zero
|
warning: attempt to divide by zero
|
||||||
--> $DIR/promoted_errors.rs:14:14
|
--> $DIR/promoted_errors.rs:15:14
|
||||||
|
|
|
|
||||||
LL | let _x = 1 / (1 - 1);
|
LL | let _x = 1 / (1 - 1);
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
warning: attempt to divide by zero
|
warning: attempt to divide by zero
|
||||||
--> $DIR/promoted_errors.rs:16:20
|
--> $DIR/promoted_errors.rs:17:20
|
||||||
|
|
|
|
||||||
LL | println!("{}", 1 / (false as u32));
|
LL | println!("{}", 1 / (false as u32));
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
warning: reaching this expression at runtime will panic or abort
|
warning: reaching this expression at runtime will panic or abort
|
||||||
--> $DIR/promoted_errors.rs:16:20
|
--> $DIR/promoted_errors.rs:17:20
|
||||||
|
|
|
|
||||||
LL | println!("{}", 1 / (false as u32));
|
LL | println!("{}", 1 / (false as u32));
|
||||||
| ^^^^^^^^^^^^^^^^^^ dividing by zero
|
| ^^^^^^^^^^^^^^^^^^ dividing by zero
|
||||||
|
|
||||||
warning: erroneous constant used
|
warning: erroneous constant used
|
||||||
--> $DIR/promoted_errors.rs:16:20
|
--> $DIR/promoted_errors.rs:17:20
|
||||||
|
|
|
|
||||||
LL | println!("{}", 1 / (false as u32));
|
LL | println!("{}", 1 / (false as u32));
|
||||||
| ^^^^^^^^^^^^^^^^^^ referenced constant has errors
|
| ^^^^^^^^^^^^^^^^^^ referenced constant has errors
|
||||||
|
|
||||||
warning: attempt to divide by zero
|
warning: attempt to divide by zero
|
||||||
--> $DIR/promoted_errors.rs:20:14
|
--> $DIR/promoted_errors.rs:21:14
|
||||||
|
|
|
|
||||||
LL | let _x = 1 / (false as u32);
|
LL | let _x = 1 / (false as u32);
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
// build-pass
|
// build-pass
|
||||||
|
// ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors)
|
||||||
// compile-flags: -C overflow-checks=on -O
|
// compile-flags: -C overflow-checks=on -O
|
||||||
|
|
||||||
#![warn(const_err)]
|
#![warn(const_err)]
|
||||||
|
|
|
@ -1,65 +1,65 @@
|
||||||
warning: attempt to subtract with overflow
|
warning: attempt to subtract with overflow
|
||||||
--> $DIR/promoted_errors2.rs:7:20
|
--> $DIR/promoted_errors2.rs:8:20
|
||||||
|
|
|
|
||||||
LL | println!("{}", 0u32 - 1);
|
LL | println!("{}", 0u32 - 1);
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
|
|
||||||
note: lint level defined here
|
note: lint level defined here
|
||||||
--> $DIR/promoted_errors2.rs:4:9
|
--> $DIR/promoted_errors2.rs:5:9
|
||||||
|
|
|
|
||||||
LL | #![warn(const_err)]
|
LL | #![warn(const_err)]
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
|
|
||||||
warning: attempt to subtract with overflow
|
warning: attempt to subtract with overflow
|
||||||
--> $DIR/promoted_errors2.rs:9:14
|
--> $DIR/promoted_errors2.rs:10:14
|
||||||
|
|
|
|
||||||
LL | let _x = 0u32 - 1;
|
LL | let _x = 0u32 - 1;
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
||||||
warning: attempt to divide by zero
|
warning: attempt to divide by zero
|
||||||
--> $DIR/promoted_errors2.rs:11:20
|
--> $DIR/promoted_errors2.rs:12:20
|
||||||
|
|
|
|
||||||
LL | println!("{}", 1 / (1 - 1));
|
LL | println!("{}", 1 / (1 - 1));
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
warning: reaching this expression at runtime will panic or abort
|
warning: reaching this expression at runtime will panic or abort
|
||||||
--> $DIR/promoted_errors2.rs:11:20
|
--> $DIR/promoted_errors2.rs:12:20
|
||||||
|
|
|
|
||||||
LL | println!("{}", 1 / (1 - 1));
|
LL | println!("{}", 1 / (1 - 1));
|
||||||
| ^^^^^^^^^^^ dividing by zero
|
| ^^^^^^^^^^^ dividing by zero
|
||||||
|
|
||||||
warning: erroneous constant used
|
warning: erroneous constant used
|
||||||
--> $DIR/promoted_errors2.rs:11:20
|
--> $DIR/promoted_errors2.rs:12:20
|
||||||
|
|
|
|
||||||
LL | println!("{}", 1 / (1 - 1));
|
LL | println!("{}", 1 / (1 - 1));
|
||||||
| ^^^^^^^^^^^ referenced constant has errors
|
| ^^^^^^^^^^^ referenced constant has errors
|
||||||
|
|
||||||
warning: attempt to divide by zero
|
warning: attempt to divide by zero
|
||||||
--> $DIR/promoted_errors2.rs:15:14
|
--> $DIR/promoted_errors2.rs:16:14
|
||||||
|
|
|
|
||||||
LL | let _x = 1 / (1 - 1);
|
LL | let _x = 1 / (1 - 1);
|
||||||
| ^^^^^^^^^^^
|
| ^^^^^^^^^^^
|
||||||
|
|
||||||
warning: attempt to divide by zero
|
warning: attempt to divide by zero
|
||||||
--> $DIR/promoted_errors2.rs:17:20
|
--> $DIR/promoted_errors2.rs:18:20
|
||||||
|
|
|
|
||||||
LL | println!("{}", 1 / (false as u32));
|
LL | println!("{}", 1 / (false as u32));
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
warning: reaching this expression at runtime will panic or abort
|
warning: reaching this expression at runtime will panic or abort
|
||||||
--> $DIR/promoted_errors2.rs:17:20
|
--> $DIR/promoted_errors2.rs:18:20
|
||||||
|
|
|
|
||||||
LL | println!("{}", 1 / (false as u32));
|
LL | println!("{}", 1 / (false as u32));
|
||||||
| ^^^^^^^^^^^^^^^^^^ dividing by zero
|
| ^^^^^^^^^^^^^^^^^^ dividing by zero
|
||||||
|
|
||||||
warning: erroneous constant used
|
warning: erroneous constant used
|
||||||
--> $DIR/promoted_errors2.rs:17:20
|
--> $DIR/promoted_errors2.rs:18:20
|
||||||
|
|
|
|
||||||
LL | println!("{}", 1 / (false as u32));
|
LL | println!("{}", 1 / (false as u32));
|
||||||
| ^^^^^^^^^^^^^^^^^^ referenced constant has errors
|
| ^^^^^^^^^^^^^^^^^^ referenced constant has errors
|
||||||
|
|
||||||
warning: attempt to divide by zero
|
warning: attempt to divide by zero
|
||||||
--> $DIR/promoted_errors2.rs:21:14
|
--> $DIR/promoted_errors2.rs:22:14
|
||||||
|
|
|
|
||||||
LL | let _x = 1 / (false as u32);
|
LL | let _x = 1 / (false as u32);
|
||||||
| ^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^
|
||||||
|
|
43
src/test/ui/consts/issue-68264-overflow.rs
Normal file
43
src/test/ui/consts/issue-68264-overflow.rs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
// check-pass
|
||||||
|
// compile-flags: --emit=mir,link
|
||||||
|
// Regression test for issue #68264
|
||||||
|
// Checks that we don't encounter overflow
|
||||||
|
// when running const-prop on functions with
|
||||||
|
// complicated bounds
|
||||||
|
pub trait Query {}
|
||||||
|
|
||||||
|
pub trait AsQuery {
|
||||||
|
type Query: Query;
|
||||||
|
}
|
||||||
|
pub trait Table: AsQuery + Sized {}
|
||||||
|
|
||||||
|
pub trait LimitDsl {
|
||||||
|
type Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) trait LoadQuery<Conn, U>: RunQueryDsl<Conn> {}
|
||||||
|
|
||||||
|
impl<T: Query> AsQuery for T {
|
||||||
|
type Query = Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> LimitDsl for T
|
||||||
|
where
|
||||||
|
T: Table,
|
||||||
|
T::Query: LimitDsl,
|
||||||
|
{
|
||||||
|
type Output = <T::Query as LimitDsl>::Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) trait RunQueryDsl<Conn>: Sized {
|
||||||
|
fn first<U>(self, _conn: &Conn) -> U
|
||||||
|
where
|
||||||
|
Self: LimitDsl,
|
||||||
|
Self::Output: LoadQuery<Conn, U>,
|
||||||
|
{
|
||||||
|
// Overflow is caused by this function body
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
19
src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs
Normal file
19
src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// run-pass
|
||||||
|
|
||||||
|
#![feature(track_caller)]
|
||||||
|
|
||||||
|
fn pass_to_ptr_call<T>(f: fn(T), x: T) {
|
||||||
|
f(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn tracked_unit(_: ()) {
|
||||||
|
let expected_line = line!() - 1;
|
||||||
|
let location = std::panic::Location::caller();
|
||||||
|
assert_eq!(location.file(), file!());
|
||||||
|
assert_eq!(location.line(), expected_line, "call shims report location as fn definition");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
pass_to_ptr_call(tracked_unit, ());
|
||||||
|
}
|
19
src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs
Normal file
19
src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// run-pass
|
||||||
|
|
||||||
|
#![feature(track_caller)]
|
||||||
|
|
||||||
|
fn ptr_call(f: fn()) {
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
fn tracked() {
|
||||||
|
let expected_line = line!() - 1;
|
||||||
|
let location = std::panic::Location::caller();
|
||||||
|
assert_eq!(location.file(), file!());
|
||||||
|
assert_eq!(location.line(), expected_line, "call shims report location as fn definition");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
ptr_call(tracked);
|
||||||
|
}
|
|
@ -110,6 +110,7 @@ static TARGETS: &[&str] = &[
|
||||||
"riscv32imac-unknown-none-elf",
|
"riscv32imac-unknown-none-elf",
|
||||||
"riscv64imac-unknown-none-elf",
|
"riscv64imac-unknown-none-elf",
|
||||||
"riscv64gc-unknown-none-elf",
|
"riscv64gc-unknown-none-elf",
|
||||||
|
"riscv64gc-unknown-linux-gnu",
|
||||||
"s390x-unknown-linux-gnu",
|
"s390x-unknown-linux-gnu",
|
||||||
"sparc64-unknown-linux-gnu",
|
"sparc64-unknown-linux-gnu",
|
||||||
"sparcv9-sun-solaris",
|
"sparcv9-sun-solaris",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue