diff --git a/LICENSE-APACHE b/LICENSE-APACHE index 16fe87b06e802..1b5ec8b78e237 100644 --- a/LICENSE-APACHE +++ b/LICENSE-APACHE @@ -174,28 +174,3 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION of your accepting any such warranty or additional liability. 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. diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index 4354e1c7b5f69..09f743fb81e4c 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -525,7 +525,8 @@ pub unsafe trait GlobalAlloc { /// The memory may or may not have been deallocated, /// and should be considered unusable (unless of course it was /// 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 /// block has not been transferred to this allocator, and the diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index e68f3c58a3e07..900ef63f1dfcc 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -10,7 +10,6 @@ use crate::mem; use crate::num::flt2dec; use crate::ops::Deref; use crate::result; -use crate::slice; use crate::str; mod builders; @@ -234,8 +233,6 @@ pub struct Formatter<'a> { precision: Option, 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, @@ -1043,8 +1040,6 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { buf: output, align: rt::v1::Alignment::Unknown, fill: ' ', - args: args.args, - curarg: args.args.iter(), }; let mut idx = 0; @@ -1063,7 +1058,7 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { // a string piece. for (arg, piece) in fmt.iter().zip(args.pieces.iter()) { formatter.buf.write_str(*piece)?; - formatter.run(arg)?; + run(&mut formatter, arg, &args.args)?; idx += 1; } } @@ -1077,6 +1072,39 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result { 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 { + 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`. #[must_use = "don't forget to write the post padding"] struct PostPadding { @@ -1114,41 +1142,6 @@ impl<'a> Formatter<'a> { align: self.align, width: self.width, 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 { - 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(), } } diff --git a/src/libcore/fmt/rt/v1.rs b/src/libcore/fmt/rt/v1.rs index 826ae36d2d100..fd81f93242b89 100644 --- a/src/libcore/fmt/rt/v1.rs +++ b/src/libcore/fmt/rt/v1.rs @@ -7,7 +7,10 @@ #[derive(Copy, Clone)] pub struct Argument { + #[cfg(bootstrap)] pub position: Position, + #[cfg(not(bootstrap))] + pub position: usize, pub format: FormatSpec, } @@ -37,12 +40,11 @@ pub enum Alignment { pub enum Count { Is(usize), Param(usize), - NextParam, Implied, } +#[cfg(bootstrap)] #[derive(Copy, Clone)] pub enum Position { - Next, At(usize), } diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index e7a4c5b592105..51ce575e51f3b 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -1,7 +1,6 @@ use crate::dep_graph::{DepConstructor, DepNode, WorkProduct, WorkProductId}; use crate::ich::{Fingerprint, NodeIdHashingMode, StableHashingContext}; use crate::session::config::OptLevel; -use crate::traits::TraitQueryMode; use crate::ty::print::obsolete::DefPathBasedNames; use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt}; use rustc_data_structures::base_n; @@ -168,9 +167,7 @@ impl<'tcx> MonoItem<'tcx> { MonoItem::GlobalAsm(..) => return true, }; - // We shouldn't encounter any overflow here, so we use TraitQueryMode::Standard\ - // to report an error if overflow somehow occurs. - tcx.substitute_normalize_and_test_predicates((def_id, &substs, TraitQueryMode::Standard)) + tcx.substitute_normalize_and_test_predicates((def_id, &substs)) } pub fn to_string(&self, tcx: TyCtxt<'tcx>, debug: bool) -> String { diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index b7aef0c44d9ee..deb2d6ac630ac 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -1156,11 +1156,11 @@ rustc_queries! { 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 desc { |tcx| - "testing substituted normalized predicates in mode {:?}:`{}`", - key.2, tcx.def_path_str(key.0) + "testing substituted normalized predicates:`{}`", + tcx.def_path_str(key.0) } } diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 9e5abc80822c7..46ece6fc40593 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -16,7 +16,6 @@ use super::CodeSelectionError; use super::{ConstEvalFailure, Unimplemented}; use super::{FulfillmentError, FulfillmentErrorCode}; use super::{ObligationCause, PredicateObligation}; -use crate::traits::TraitQueryMode; impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> { type Predicate = ty::Predicate<'tcx>; @@ -63,9 +62,6 @@ pub struct FulfillmentContext<'tcx> { // a snapshot (they don't *straddle* a snapshot, so there // is no trouble there). usable_in_snapshot: bool, - - // The `TraitQueryMode` used when constructing a `SelectionContext` - query_mode: TraitQueryMode, } #[derive(Clone, Debug)] @@ -79,26 +75,12 @@ pub struct PendingPredicateObligation<'tcx> { static_assert_size!(PendingPredicateObligation<'_>, 136); impl<'a, 'tcx> FulfillmentContext<'tcx> { - /// Creates a new fulfillment context with `TraitQueryMode::Standard` - /// You almost always want to use this instead of `with_query_mode` + /// Creates a new fulfillment context. pub fn new() -> FulfillmentContext<'tcx> { FulfillmentContext { predicates: ObligationForest::new(), register_region_obligations: true, 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(), register_region_obligations: true, usable_in_snapshot: true, - query_mode: TraitQueryMode::Standard, } } @@ -116,7 +97,6 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> { predicates: ObligationForest::new(), register_region_obligations: false, usable_in_snapshot: false, - query_mode: TraitQueryMode::Standard, } } @@ -237,7 +217,7 @@ impl<'tcx> TraitEngine<'tcx> for FulfillmentContext<'tcx> { &mut self, infcx: &InferCtxt<'_, 'tcx>, ) -> Result<(), Vec>> { - let mut selcx = SelectionContext::with_query_mode(infcx, self.query_mode); + let mut selcx = SelectionContext::new(infcx); self.select(&mut selcx) } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 2e5da2b038254..e93529186ac86 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -95,7 +95,7 @@ pub enum IntercrateMode { } /// The mode that trait queries run in. -#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, HashStable)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum TraitQueryMode { // Standard/un-canonicalized queries get accurate // spans etc. passed in and hence can do reasonable @@ -1014,17 +1014,16 @@ where /// environment. If this returns false, then either normalize /// encountered an error or one of the predicates did not hold. Used /// when creating vtables to check for unsatisfiable methods. -fn normalize_and_test_predicates<'tcx>( +pub fn normalize_and_test_predicates<'tcx>( tcx: TyCtxt<'tcx>, predicates: Vec>, - mode: TraitQueryMode, ) -> 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 param_env = ty::ParamEnv::reveal_all(); - let mut selcx = SelectionContext::with_query_mode(&infcx, mode); - let mut fulfill_cx = FulfillmentContext::with_query_mode(mode); + let mut selcx = SelectionContext::new(&infcx); + let mut fulfill_cx = FulfillmentContext::new(); let cause = ObligationCause::dummy(); let Normalized { value: predicates, obligations } = 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>( tcx: TyCtxt<'tcx>, - key: (DefId, SubstsRef<'tcx>, TraitQueryMode), + key: (DefId, SubstsRef<'tcx>), ) -> bool { debug!("substitute_normalize_and_test_predicates(key={:?})", key); 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); result @@ -1102,10 +1101,7 @@ fn vtable_methods<'tcx>( // Note that this method could then never be called, so we // do not want to try and codegen it, in that case (see #23435). 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 - // up happening. - if !normalize_and_test_predicates(tcx, predicates.predicates, TraitQueryMode::Standard) - { + if !normalize_and_test_predicates(tcx, predicates.predicates) { debug!("vtable_methods: predicates do not hold"); return None; } diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 9be50d19a5030..1ea695e40b255 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -141,7 +141,12 @@ impl<'tcx> InstanceDef<'tcx> { } 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, + } } } diff --git a/src/librustc/ty/query/keys.rs b/src/librustc/ty/query/keys.rs index 3fb3720a5638a..cbf335ad607ef 100644 --- a/src/librustc/ty/query/keys.rs +++ b/src/librustc/ty/query/keys.rs @@ -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>) { fn query_crate(&self) -> CrateNum { self.1.def_id().krate diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs index 6fca74e223944..3f4e24ca993db 100644 --- a/src/librustc_builtin_macros/format.rs +++ b/src/librustc_builtin_macros/format.rs @@ -590,17 +590,6 @@ impl<'a, 'b> Context<'a, 'b> { parse::NextArgument(ref arg) => { // Build the position 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 { parse::ArgumentIs(i) | parse::ArgumentImplicitlyIs(i) => { // Map to index in final generated argument array @@ -615,7 +604,7 @@ impl<'a, 'b> Context<'a, 'b> { arg_idx } }; - pos("At", Some(arg_idx)) + self.ecx.expr_usize(sp, arg_idx) } // should never be the case, because names are already diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 01cecdd067945..b84616142cb07 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -31,9 +31,13 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx let mut result = match instance { ty::InstanceDef::Item(..) => bug!("item {:?} passed to make_shim", instance), - ty::InstanceDef::VtableShim(def_id) => { - build_call_shim(tcx, instance, Adjustment::DerefMove, CallKind::Direct(def_id), None) - } + ty::InstanceDef::VtableShim(def_id) => build_call_shim( + tcx, + instance, + Some(Adjustment::DerefMove), + CallKind::Direct(def_id), + None, + ), ty::InstanceDef::FnPtrShim(def_id, ty) => { let trait_ = tcx.trait_of_item(def_id).unwrap(); 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 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 // 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 // (such as `#[track_caller]`). 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: _ } => { 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() .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::CloneShim(def_id, ty) => { @@ -648,7 +658,7 @@ impl CloneShimBuilder<'tcx> { fn build_call_shim<'tcx>( tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>, - rcvr_adjustment: Adjustment, + rcvr_adjustment: Option, call_kind: CallKind, untuple_args: Option<&[Ty<'tcx>]>, ) -> BodyAndCache<'tcx> { @@ -680,14 +690,16 @@ fn build_call_shim<'tcx>( let mut local_decls = local_decls_for_sig(&sig, span); let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE }; - let rcvr_arg = Local::new(1 + 0); - let rcvr_l = Place::from(rcvr_arg); + let rcvr_place = || { + assert!(rcvr_adjustment.is_some()); + Place::from(Local::new(1 + 0)) + }; let mut statements = vec![]; - let rcvr = match rcvr_adjustment { - Adjustment::Identity => Operand::Move(rcvr_l), - Adjustment::Deref => Operand::Copy(tcx.mk_place_deref(rcvr_l)), - Adjustment::DerefMove => Operand::Move(tcx.mk_place_deref(rcvr_l)), + let rcvr = rcvr_adjustment.map(|rcvr_adjustment| match rcvr_adjustment { + Adjustment::Identity => Operand::Move(rcvr_place()), + Adjustment::Deref => Operand::Copy(tcx.mk_place_deref(rcvr_place())), + Adjustment::DerefMove => Operand::Move(tcx.mk_place_deref(rcvr_place())), Adjustment::RefMut => { // let rcvr = &mut rcvr; let ref_rcvr = local_decls.push(temp_decl( @@ -703,15 +715,15 @@ fn build_call_shim<'tcx>( source_info, kind: StatementKind::Assign(box ( 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)) } - }; + }); let (callee, mut args) = match call_kind { - CallKind::Indirect => (rcvr, vec![]), + CallKind::Indirect => (rcvr.unwrap(), vec![]), CallKind::Direct(def_id) => { let ty = tcx.type_of(def_id); ( @@ -720,21 +732,35 @@ fn build_call_shim<'tcx>( user_ty: None, literal: ty::Const::zero_sized(tcx, ty), }), - vec![rcvr], + rcvr.into_iter().collect::>(), ) } }; + let mut arg_range = 0..sig.inputs().len(); + + // Take the `self` ("receiver") argument out of the range (it's adjusted above). + if rcvr_adjustment.is_some() { + arg_range.start += 1; + } + + // 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)| { - let arg_place = Place::from(Local::new(1 + 1)); - Operand::Move(tcx.mk_place_field(arg_place, Field::new(i), *ity)) + Operand::Move(tcx.mk_place_field(Place::from(tuple_arg), Field::new(i), *ity)) })); - } 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 }; + let n_blocks = if let Some(Adjustment::RefMut) = rcvr_adjustment { 5 } else { 2 }; let mut blocks = IndexVec::with_capacity(n_blocks); let block = |blocks: &mut IndexVec<_, _>, statements, kind, is_cleanup| { blocks.push(BasicBlockData { @@ -752,7 +778,7 @@ fn build_call_shim<'tcx>( func: callee, args, 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)) } else { None @@ -762,13 +788,13 @@ fn build_call_shim<'tcx>( false, ); - if let Adjustment::RefMut = rcvr_adjustment { + if let Some(Adjustment::RefMut) = rcvr_adjustment { // BB #1 - drop for Self block( &mut blocks, vec![], TerminatorKind::Drop { - location: Place::from(rcvr_arg), + location: rcvr_place(), target: BasicBlock::new(2), unwind: None, }, @@ -777,13 +803,13 @@ fn build_call_shim<'tcx>( } // BB #1/#2 - return 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 block( &mut blocks, vec![], TerminatorKind::Drop { - location: Place::from(rcvr_arg), + location: rcvr_place(), target: BasicBlock::new(4), unwind: None, }, diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index bd398c6e5b449..d645f6cf183b4 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -14,7 +14,7 @@ use rustc::mir::{ SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE, }; -use rustc::traits::TraitQueryMode; +use rustc::traits; use rustc::ty::layout::{ 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 // off, and we just give up. // - // Note that we use TraitQueryMode::Canonical here, which causes - // us to treat overflow like any other error. This is because we - // are "speculatively" evaluating this item with the default substs. - // While this usually succeeds, it may fail with tricky impls - // (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. + // We manually filter the predicates, skipping anything that's not + // "global". We are in a potentially generic context + // (e.g. we are evaluating a function without substituting generic + // parameters, so this filtering serves two purposes: // - // False negatives (failing to run const-prop on something when we actually - // could) are fine. However, false positives (running const-prop on - // an item with unsatisfiable bounds) can lead to us generating invalid - // MIR. - if !tcx.substitute_normalize_and_test_predicates(( - source.def_id(), - InternalSubsts::identity_for_item(tcx, source.def_id()), - TraitQueryMode::Canonical, - )) { - trace!( - "ConstProp skipped for item with unsatisfiable predicates: {:?}", - source.def_id() - ); + // 1. We skip evaluating any predicates that we would + // never be able prove are unsatisfiable (e.g. `` + // 2. We avoid trying to normalize predicates involving generic + // parameters (e.g. `::MyItem`). This can confuse + // the normalization code (leading to cycle errors), since + // it's usually never invoked in this way. + let predicates = tcx + .predicates_of(source.def_id()) + .predicates + .iter() + .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }) + .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; } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 9406803825350..ab38eec5f3ea9 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2321,8 +2321,8 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func "{}{}{}{}{:#}fn {}{:#}", it.visibility.print_with_space(), f.header.constness.print_with_space(), - f.header.unsafety.print_with_space(), f.header.asyncness.print_with_space(), + f.header.unsafety.print_with_space(), print_abi_with_space(f.header.abi), it.name.as_ref().unwrap(), 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); write!( w, - "{vis}{constness}{unsafety}{asyncness}{abi}fn \ + "{vis}{constness}{asyncness}{unsafety}{abi}fn \ {name}{generics}{decl}{where_clause}", vis = it.visibility.print_with_space(), constness = f.header.constness.print_with_space(), - unsafety = f.header.unsafety.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), name = it.name.as_ref().unwrap(), generics = f.generics.print(), @@ -2832,8 +2832,8 @@ fn render_assoc_item( "{}{}{}{}{}{:#}fn {}{:#}", meth.visibility.print_with_space(), header.constness.print_with_space(), - header.unsafety.print_with_space(), header.asyncness.print_with_space(), + header.unsafety.print_with_space(), print_default_space(meth.is_default()), print_abi_with_space(header.abi), name, @@ -2854,8 +2854,8 @@ fn render_assoc_item( if parent == ItemType::Trait { " " } else { "" }, meth.visibility.print_with_space(), header.constness.print_with_space(), - header.unsafety.print_with_space(), header.asyncness.print_with_space(), + header.unsafety.print_with_space(), print_default_space(meth.is_default()), print_abi_with_space(header.abi), href = href, diff --git a/src/test/rustdoc/async-fn.rs b/src/test/rustdoc/async-fn.rs index 5f9708a39722a..5a03e821e8a2f 100644 --- a/src/test/rustdoc/async-fn.rs +++ b/src/test/rustdoc/async-fn.rs @@ -15,6 +15,11 @@ pub async fn baz(a: T) -> T { 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 {} impl Bar for () {} @@ -26,8 +31,10 @@ pub async fn quux() -> impl Bar { // @has async_fn/struct.Foo.html // @matches - '//code' 'pub async fn f\(\)$' +// @matches - '//code' 'pub async unsafe fn g\(\)$' pub struct Foo; impl Foo { pub async fn f() {} + pub async unsafe fn g() {} } diff --git a/src/test/ui/async-await/async-fn-nonsend.rs b/src/test/ui/async-await/async-fn-nonsend.rs index 645c903c6bab2..ceeebbca5195a 100644 --- a/src/test/ui/async-await/async-fn-nonsend.rs +++ b/src/test/ui/async-await/async-fn-nonsend.rs @@ -2,15 +2,15 @@ // edition:2018 // compile-flags: --crate-type lib -use std::{ - cell::RefCell, - fmt::Debug, - rc::Rc, -}; +use std::{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) {} @@ -53,5 +53,4 @@ pub fn pass_assert() { //~^ ERROR future cannot be sent between threads safely assert_send(non_sync_with_method_call()); //~^ ERROR future cannot be sent between threads safely - //~^^ ERROR future cannot be sent between threads safely } diff --git a/src/test/ui/async-await/async-fn-nonsend.stderr b/src/test/ui/async-await/async-fn-nonsend.stderr index 5c870ca2d0276..105fd23ecfb66 100644 --- a/src/test/ui/async-await/async-fn-nonsend.stderr +++ b/src/test/ui/async-await/async-fn-nonsend.stderr @@ -62,27 +62,5 @@ LL | } LL | } | - `f` is later dropped here -error: future cannot be sent between threads safely - --> $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 +error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/array-literal-index-oob.rs b/src/test/ui/consts/array-literal-index-oob.rs index 64aeb46894d16..af63d1f75a770 100644 --- a/src/test/ui/consts/array-literal-index-oob.rs +++ b/src/test/ui/consts/array-literal-index-oob.rs @@ -1,4 +1,5 @@ // build-pass +// ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors) #![warn(const_err)] diff --git a/src/test/ui/consts/array-literal-index-oob.stderr b/src/test/ui/consts/array-literal-index-oob.stderr index 50ad8e83e905c..e93aa324784c3 100644 --- a/src/test/ui/consts/array-literal-index-oob.stderr +++ b/src/test/ui/consts/array-literal-index-oob.stderr @@ -1,17 +1,17 @@ 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] }; | ^^^^^^^^^^^^ | 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)] | ^^^^^^^^^ 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] }; | ---^^^^^^^^^^^^-- @@ -19,7 +19,7 @@ LL | &{ [1, 2, 3][4] }; | indexing out of bounds: the len is 3 but the index is 4 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] }; | ^^^^^^^^^^^^^^^^^ referenced constant has errors diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs index fee232185d29a..22f863fb15ac4 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.rs +++ b/src/test/ui/consts/const-eval/promoted_errors.rs @@ -1,4 +1,5 @@ // build-pass +// ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors) // compile-flags: -O #![warn(const_err)] diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr index 4de22fdf4ab1e..b4330deb3ef10 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors.stderr @@ -1,59 +1,59 @@ warning: this expression will panic at runtime - --> $DIR/promoted_errors.rs:8:14 + --> $DIR/promoted_errors.rs:9:14 | LL | let _x = 0u32 - 1; | ^^^^^^^^ attempt to subtract with overflow | note: lint level defined here - --> $DIR/promoted_errors.rs:4:9 + --> $DIR/promoted_errors.rs:5:9 | LL | #![warn(const_err)] | ^^^^^^^^^ warning: attempt to divide by zero - --> $DIR/promoted_errors.rs:10:20 + --> $DIR/promoted_errors.rs:11:20 | LL | println!("{}", 1 / (1 - 1)); | ^^^^^^^^^^^ 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)); | ^^^^^^^^^^^ dividing by zero warning: erroneous constant used - --> $DIR/promoted_errors.rs:10:20 + --> $DIR/promoted_errors.rs:11:20 | LL | println!("{}", 1 / (1 - 1)); | ^^^^^^^^^^^ referenced constant has errors warning: attempt to divide by zero - --> $DIR/promoted_errors.rs:14:14 + --> $DIR/promoted_errors.rs:15:14 | LL | let _x = 1 / (1 - 1); | ^^^^^^^^^^^ warning: attempt to divide by zero - --> $DIR/promoted_errors.rs:16:20 + --> $DIR/promoted_errors.rs:17:20 | LL | println!("{}", 1 / (false as u32)); | ^^^^^^^^^^^^^^^^^^ 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)); | ^^^^^^^^^^^^^^^^^^ dividing by zero warning: erroneous constant used - --> $DIR/promoted_errors.rs:16:20 + --> $DIR/promoted_errors.rs:17:20 | LL | println!("{}", 1 / (false as u32)); | ^^^^^^^^^^^^^^^^^^ referenced constant has errors 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); | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/consts/const-eval/promoted_errors2.rs b/src/test/ui/consts/const-eval/promoted_errors2.rs index 41a989d91c5d3..62c77f76d9064 100644 --- a/src/test/ui/consts/const-eval/promoted_errors2.rs +++ b/src/test/ui/consts/const-eval/promoted_errors2.rs @@ -1,4 +1,5 @@ // 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 #![warn(const_err)] diff --git a/src/test/ui/consts/const-eval/promoted_errors2.stderr b/src/test/ui/consts/const-eval/promoted_errors2.stderr index 4f7ba8bf385d3..a4dad295edd79 100644 --- a/src/test/ui/consts/const-eval/promoted_errors2.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors2.stderr @@ -1,65 +1,65 @@ warning: attempt to subtract with overflow - --> $DIR/promoted_errors2.rs:7:20 + --> $DIR/promoted_errors2.rs:8:20 | LL | println!("{}", 0u32 - 1); | ^^^^^^^^ | note: lint level defined here - --> $DIR/promoted_errors2.rs:4:9 + --> $DIR/promoted_errors2.rs:5:9 | LL | #![warn(const_err)] | ^^^^^^^^^ warning: attempt to subtract with overflow - --> $DIR/promoted_errors2.rs:9:14 + --> $DIR/promoted_errors2.rs:10:14 | LL | let _x = 0u32 - 1; | ^^^^^^^^ warning: attempt to divide by zero - --> $DIR/promoted_errors2.rs:11:20 + --> $DIR/promoted_errors2.rs:12:20 | LL | println!("{}", 1 / (1 - 1)); | ^^^^^^^^^^^ 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)); | ^^^^^^^^^^^ dividing by zero warning: erroneous constant used - --> $DIR/promoted_errors2.rs:11:20 + --> $DIR/promoted_errors2.rs:12:20 | LL | println!("{}", 1 / (1 - 1)); | ^^^^^^^^^^^ referenced constant has errors warning: attempt to divide by zero - --> $DIR/promoted_errors2.rs:15:14 + --> $DIR/promoted_errors2.rs:16:14 | LL | let _x = 1 / (1 - 1); | ^^^^^^^^^^^ warning: attempt to divide by zero - --> $DIR/promoted_errors2.rs:17:20 + --> $DIR/promoted_errors2.rs:18:20 | LL | println!("{}", 1 / (false as u32)); | ^^^^^^^^^^^^^^^^^^ 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)); | ^^^^^^^^^^^^^^^^^^ dividing by zero warning: erroneous constant used - --> $DIR/promoted_errors2.rs:17:20 + --> $DIR/promoted_errors2.rs:18:20 | LL | println!("{}", 1 / (false as u32)); | ^^^^^^^^^^^^^^^^^^ referenced constant has errors 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); | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/consts/issue-68264-overflow.rs b/src/test/ui/consts/issue-68264-overflow.rs new file mode 100644 index 0000000000000..8f21e0648d4c7 --- /dev/null +++ b/src/test/ui/consts/issue-68264-overflow.rs @@ -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: RunQueryDsl {} + +impl AsQuery for T { + type Query = Self; +} + +impl LimitDsl for T +where + T: Table, + T::Query: LimitDsl, +{ + type Output = ::Output; +} + +pub(crate) trait RunQueryDsl: Sized { + fn first(self, _conn: &Conn) -> U + where + Self: LimitDsl, + Self::Output: LoadQuery, + { + // Overflow is caused by this function body + unimplemented!() + } +} + +fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs new file mode 100644 index 0000000000000..0407eafbfd41c --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr-with-arg.rs @@ -0,0 +1,19 @@ +// run-pass + +#![feature(track_caller)] + +fn pass_to_ptr_call(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, ()); +} diff --git a/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs new file mode 100644 index 0000000000000..a4baaa26ced1e --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/tracked-fn-ptr.rs @@ -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); +} diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 481163a1a9abe..cff04e197e48a 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -110,6 +110,7 @@ static TARGETS: &[&str] = &[ "riscv32imac-unknown-none-elf", "riscv64imac-unknown-none-elf", "riscv64gc-unknown-none-elf", + "riscv64gc-unknown-linux-gnu", "s390x-unknown-linux-gnu", "sparc64-unknown-linux-gnu", "sparcv9-sun-solaris",