diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 450cdf246b1..db0d8b08a94 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -11,7 +11,7 @@ use super::LoweringContext; use rustc_ast::ptr::P; use rustc_ast::*; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::definitions::DefPathData; @@ -71,7 +71,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .emit(); } - let mut clobber_abis = FxHashMap::default(); + let mut clobber_abis = FxIndexMap::default(); if let Some(asm_arch) = asm_arch { for (abi_name, abi_span) in &asm.clobber_abis { match asm::InlineAsmClobberAbi::parse(asm_arch, &self.tcx.sess.target, *abi_name) { diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index eb64027f369..01716859a9d 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -655,15 +655,40 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ExprKind::Closure(c) }; - let generator = hir::Expr { - hir_id: self.lower_node_id(closure_node_id), - kind: generator_kind, - span: self.lower_span(span), - }; - - // `future::from_generator`: + let parent_has_track_caller = self + .attrs + .values() + .find(|attrs| attrs.into_iter().find(|attr| attr.has_name(sym::track_caller)).is_some()) + .is_some(); let unstable_span = self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); + + let hir_id = if parent_has_track_caller { + let generator_hir_id = self.lower_node_id(closure_node_id); + self.lower_attrs( + generator_hir_id, + &[Attribute { + kind: AttrKind::Normal(ptr::P(NormalAttr { + item: AttrItem { + path: Path::from_ident(Ident::new(sym::track_caller, span)), + args: MacArgs::Empty, + tokens: None, + }, + tokens: None, + })), + id: self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id(), + style: AttrStyle::Outer, + span: unstable_span, + }], + ); + generator_hir_id + } else { + self.lower_node_id(closure_node_id) + }; + + let generator = hir::Expr { hir_id, kind: generator_kind, span: self.lower_span(span) }; + + // `future::from_generator`: let gen_future = self.expr_lang_item_path( unstable_span, hir::LangItem::FromGenerator, diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 756f35e901d..77c5ed6036e 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -6,7 +6,6 @@ use super::{FnDeclKind, LoweringContext, ParamMode}; use rustc_ast::ptr::P; use rustc_ast::visit::AssocCtxt; use rustc_ast::*; -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sorted_map::SortedMap; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -67,7 +66,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { // HirId handling. bodies: Vec::new(), attrs: SortedMap::default(), - children: FxHashMap::default(), + children: Vec::default(), current_hir_id_owner: hir::CRATE_OWNER_ID, item_local_id_counter: hir::ItemLocalId::new(0), node_id_to_local_id: Default::default(), @@ -86,7 +85,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { impl_trait_defs: Vec::new(), impl_trait_bounds: Vec::new(), allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()), - allow_gen_future: Some([sym::gen_future][..].into()), + allow_gen_future: Some([sym::gen_future, sym::closure_track_caller][..].into()), allow_into_future: Some([sym::into_future][..].into()), generics_def_id_map: Default::default(), }; @@ -534,12 +533,12 @@ impl<'hir> LoweringContext<'_, 'hir> { for new_node_id in [id1, id2] { let new_id = self.local_def_id(new_node_id); let Some(res) = resolutions.next() else { + debug_assert!(self.children.iter().find(|(id, _)| id == &new_id).is_none()); // Associate an HirId to both ids even if there is no resolution. - let _old = self.children.insert( + self.children.push(( new_id, - hir::MaybeOwner::NonOwner(hir::HirId::make_owner(new_id)), + hir::MaybeOwner::NonOwner(hir::HirId::make_owner(new_id))), ); - debug_assert!(_old.is_none()); continue; }; let ident = *ident; diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 5ab75b1294b..ecc2578dd2a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -34,7 +34,6 @@ #![feature(let_chains)] #![feature(never_type)] #![recursion_limit = "256"] -#![allow(rustc::potential_query_instability)] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] @@ -107,7 +106,7 @@ struct LoweringContext<'a, 'hir> { /// Attributes inside the owner being lowered. attrs: SortedMap, /// Collect items that were created by lowering the current owner. - children: FxHashMap>>, + children: Vec<(LocalDefId, hir::MaybeOwner<&'hir hir::OwnerInfo<'hir>>)>, generator_kind: Option, @@ -611,8 +610,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.impl_trait_defs = current_impl_trait_defs; self.impl_trait_bounds = current_impl_trait_bounds; - let _old = self.children.insert(def_id, hir::MaybeOwner::Owner(info)); - debug_assert!(_old.is_none()) + debug_assert!(self.children.iter().find(|(id, _)| id == &def_id).is_none()); + self.children.push((def_id, hir::MaybeOwner::Owner(info))); } /// Installs the remapping `remap` in scope while `f` is being executed. @@ -719,8 +718,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { assert_ne!(local_id, hir::ItemLocalId::new(0)); if let Some(def_id) = self.opt_local_def_id(ast_node_id) { - // Do not override a `MaybeOwner::Owner` that may already here. - self.children.entry(def_id).or_insert(hir::MaybeOwner::NonOwner(hir_id)); + self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); self.local_id_to_def_id.insert(local_id, def_id); } diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index dd222485daf..b2db77944fd 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -7,9 +7,7 @@ use rustc_infer::infer::{DefiningAnchor, InferCtxt}; use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::visit::TypeVisitable; -use rustc_middle::ty::{ - self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt, TypeFoldable, -}; +use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable}; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; use rustc_trait_selection::traits::ObligationCtxt; @@ -256,8 +254,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { // Require the hidden type to be well-formed with only the generics of the opaque type. // Defining use functions may have more bounds than the opaque type, which is ok, as long as the // hidden type is well formed even without those bounds. - let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into())) - .to_predicate(infcx.tcx); + let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(definition_ty.into())); let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id.to_def_id()); @@ -282,6 +279,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { } ocx.register_obligation(Obligation::misc( + infcx.tcx, instantiated_ty.span, body_id, param_env, diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index a581726a15c..d0cf8622a44 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -92,8 +92,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { trait_ref, constness: ty::BoundConstness::NotConst, polarity: ty::ImplPolarity::Positive, - })) - .to_predicate(self.tcx()), + })), locations, category, ); @@ -122,14 +121,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { pub(super) fn prove_predicates( &mut self, - predicates: impl IntoIterator>, + predicates: impl IntoIterator< + Item = impl ToPredicate<'tcx, ty::Predicate<'tcx>> + std::fmt::Debug, + >, locations: Locations, category: ConstraintCategory<'tcx>, ) { for predicate in predicates { - let predicate = predicate.to_predicate(self.tcx()); - debug!("prove_predicates(predicate={:?}, locations={:?})", predicate, locations,); - self.prove_predicate(predicate, locations, category); } } @@ -137,11 +135,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { #[instrument(skip(self), level = "debug")] pub(super) fn prove_predicate( &mut self, - predicate: ty::Predicate<'tcx>, + predicate: impl ToPredicate<'tcx, ty::Predicate<'tcx>> + std::fmt::Debug, locations: Locations, category: ConstraintCategory<'tcx>, ) { let param_env = self.param_env; + let predicate = predicate.to_predicate(self.tcx()); self.fully_perform_op( locations, category, diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 6ccc29b09c0..7d36a63943c 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -33,8 +33,7 @@ use rustc_middle::ty::subst::{SubstsRef, UserSubsts}; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{ self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic, - OpaqueHiddenType, OpaqueTypeKey, RegionVid, ToPredicate, Ty, TyCtxt, UserType, - UserTypeAnnotationIndex, + OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, }; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::{Span, DUMMY_SP}; @@ -1069,8 +1068,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } self.prove_predicate( - ty::Binder::dummy(ty::PredicateKind::WellFormed(inferred_ty.into())) - .to_predicate(self.tcx()), + ty::Binder::dummy(ty::PredicateKind::WellFormed(inferred_ty.into())), Locations::All(span), ConstraintCategory::TypeAnnotation, ); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 5a8b3e30b9f..36956f5dd6d 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -732,7 +732,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { polarity: ty::ImplPolarity::Positive, }); let obligation = - Obligation::new(ObligationCause::dummy(), param_env, poly_trait_pred); + Obligation::new(tcx, ObligationCause::dummy(), param_env, poly_trait_pred); let implsrc = { let infcx = tcx.infer_ctxt().build(); @@ -816,6 +816,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { if !nonconst_call_permission { let obligation = Obligation::new( + tcx, ObligationCause::dummy_with_span(*fn_span), param_env, tcx.mk_predicate( diff --git a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs index 25b420bed17..b90e0962ce6 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/mod.rs @@ -62,7 +62,7 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> { } fn is_async(&self) -> bool { - self.tcx.asyncness(self.def_id()) == hir::IsAsync::Async + self.tcx.asyncness(self.def_id()).is_async() } } diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs index b28d7019491..2d4afd0dc35 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs @@ -147,6 +147,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> { } Adt(..) => { let obligation = Obligation::new( + tcx, ObligationCause::dummy(), param_env, Binder::dummy(TraitPredicate { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index d995d533ca3..6fd12985170 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -156,6 +156,7 @@ impl Qualif for NeedsNonConstDrop { let destruct = cx.tcx.require_lang_item(LangItem::Destruct, None); let obligation = Obligation::new( + cx.tcx, ObligationCause::dummy(), cx.param_env, ty::Binder::dummy(ty::TraitPredicate { @@ -351,7 +352,11 @@ where // FIXME(valtrees): check whether const qualifs should behave the same // way for type and mir constants. let uneval = match constant.literal { - ConstantKind::Ty(ct) if matches!(ct.kind(), ty::ConstKind::Param(_)) => None, + ConstantKind::Ty(ct) + if matches!(ct.kind(), ty::ConstKind::Param(_) | ty::ConstKind::Error(_)) => + { + None + } ConstantKind::Ty(c) => bug!("expected ConstKind::Param here, found {:?}", c), ConstantKind::Unevaluated(uv, _) => Some(uv), ConstantKind::Val(..) => None, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 7d8b859a6b4..e0a38645065 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2720,6 +2720,12 @@ pub enum IsAsync { NotAsync, } +impl IsAsync { + pub fn is_async(self) -> bool { + self == IsAsync::Async + } +} + #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable, HashStable_Generic)] pub enum Defaultness { Default { has_value: bool }, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 0ba5e615101..f76b282fa76 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -19,9 +19,7 @@ use rustc_middle::middle::stability::EvalResult; use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES}; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::util::{Discr, IntTypeExt}; -use rustc_middle::ty::{ - self, ParamEnv, ToPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, -}; +use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable}; use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS}; use rustc_span::symbol::sym; use rustc_span::{self, Span}; @@ -464,9 +462,8 @@ fn check_opaque_meets_bounds<'tcx>( // Additionally require the hidden type to be well-formed with only the generics of the opaque type. // Defining use functions may have more bounds than the opaque type, which is ok, as long as the // hidden type is well formed even without those bounds. - let predicate = - ty::Binder::dummy(ty::PredicateKind::WellFormed(hidden_ty.into())).to_predicate(tcx); - ocx.register_obligation(Obligation::new(misc_cause, param_env, predicate)); + let predicate = ty::Binder::dummy(ty::PredicateKind::WellFormed(hidden_ty.into())); + ocx.register_obligation(Obligation::new(tcx, misc_cause, param_env, predicate)); // Check that all obligations are satisfied by the implementation's // version. diff --git a/compiler/rustc_hir_analysis/src/check/compare_method.rs b/compiler/rustc_hir_analysis/src/check/compare_method.rs index 7c99896b457..81672213dc7 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_method.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_method.rs @@ -238,7 +238,7 @@ fn compare_predicate_entailment<'tcx>( kind: impl_m.kind, }, ); - ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate)); + ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate)); } // We now need to check that the signature of the impl method is @@ -521,7 +521,13 @@ pub fn collect_trait_impl_trait_tys<'tcx>( let num_trait_substs = trait_to_impl_substs.len(); let num_impl_substs = tcx.generics_of(impl_m.container_id(tcx)).params.len(); let ty = tcx.fold_regions(ty, |region, _| { - let (ty::ReFree(_) | ty::ReEarlyBound(_)) = region.kind() else { return region; }; + match region.kind() { + // Remap all free regions, which correspond to late-bound regions in the function. + ty::ReFree(_) => {} + // Remap early-bound regions as long as they don't come from the `impl` itself. + ty::ReEarlyBound(ebr) if tcx.parent(ebr.def_id) != impl_m.container_id(tcx) => {} + _ => return region, + } let Some(ty::ReEarlyBound(e)) = map.get(®ion.into()).map(|r| r.expect_region().kind()) else { tcx @@ -605,6 +611,7 @@ impl<'tcx> TypeFolder<'tcx> for ImplTraitInTraitCollector<'_, 'tcx> { ); self.ocx.register_obligation(traits::Obligation::new( + self.tcx(), ObligationCause::new( self.span, self.body_id, @@ -681,9 +688,7 @@ fn report_trait_method_mismatch<'tcx>( // Suggestion to change output type. We do not suggest in `async` functions // to avoid complex logic or incorrect output. match tcx.hir().expect_impl_item(impl_m.def_id.expect_local()).kind { - ImplItemKind::Fn(ref sig, _) - if sig.header.asyncness == hir::IsAsync::NotAsync => - { + ImplItemKind::Fn(ref sig, _) if !sig.header.asyncness.is_async() => { let msg = "change the output type to match the trait"; let ap = Applicability::MachineApplicable; match sig.decl.output { @@ -1579,7 +1584,7 @@ fn compare_type_predicate_entailment<'tcx>( }, ); ocx.register_obligations(obligations); - ocx.register_obligation(traits::Obligation::new(cause, param_env, predicate)); + ocx.register_obligation(traits::Obligation::new(tcx, cause, param_env, predicate)); } // Check that all obligations are satisfied by the implementation's @@ -1784,7 +1789,7 @@ pub fn check_type_bounds<'tcx>( .subst_iter_copied(tcx, rebased_substs) .map(|(concrete_ty_bound, span)| { debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound); - traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound) + traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound) }) .collect(); debug!("check_type_bounds: item_bounds={:?}", obligations); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index efb34e4ff65..1d7ceda725a 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -14,8 +14,8 @@ use rustc_middle::mir::ConstraintCategory; use rustc_middle::ty::query::Providers; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ - self, AdtKind, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, - TypeSuperVisitable, TypeVisitable, TypeVisitor, + self, AdtKind, DefIdTree, GenericParamDefKind, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, + TypeVisitable, TypeVisitor, }; use rustc_middle::ty::{GenericArgKind, InternalSubsts}; use rustc_session::parse::feature_err; @@ -75,9 +75,10 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { // for a type to be WF, we do not need to check if const trait predicates satisfy. let param_env = self.param_env.without_const(); self.ocx.register_obligation(traits::Obligation::new( + self.tcx(), cause, param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(self.tcx()), + ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)), )); } } @@ -1111,12 +1112,12 @@ fn check_type_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, all_sized: b traits::MiscObligation, ); wfcx.register_obligation(traits::Obligation::new( + tcx, cause, wfcx.param_env, ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable( ty::Const::from_anon_const(tcx, discr_def_id.expect_local()), - )) - .to_predicate(tcx), + )), )); } } @@ -1453,7 +1454,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id wfcx.body_id, traits::ItemObligation(def_id.to_def_id()), ); - traits::Obligation::new(cause, wfcx.param_env, pred) + traits::Obligation::new(tcx, cause, wfcx.param_env, pred) }); let predicates = predicates.0.instantiate_identity(tcx); @@ -1783,8 +1784,7 @@ fn receiver_is_implemented<'tcx>( substs: tcx.mk_substs_trait(receiver_ty, &[]), }); - let obligation = - traits::Obligation::new(cause, wfcx.param_env, trait_ref.without_const().to_predicate(tcx)); + let obligation = traits::Obligation::new(tcx, cause, wfcx.param_env, trait_ref.without_const()); if wfcx.infcx.predicate_must_hold_modulo_regions(&obligation) { true @@ -1931,6 +1931,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { } let obligation = traits::Obligation::new( + tcx, traits::ObligationCause::new(span, self.body_id, traits::TrivialBound), empty_env, pred, diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index b0fdfcf38a6..4f9d5826583 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -5,7 +5,7 @@ use rustc_hir::{ForeignItem, ForeignItemKind, HirId}; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ObligationCause, WellFormedLoc}; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::{self, Region, ToPredicate, TyCtxt, TypeFoldable, TypeFolder}; +use rustc_middle::ty::{self, Region, TyCtxt, TypeFoldable, TypeFolder}; use rustc_trait_selection::traits; pub fn provide(providers: &mut Providers) { @@ -74,10 +74,10 @@ fn diagnostic_hir_wf_check<'tcx>( let errors = traits::fully_solve_obligation( &infcx, traits::Obligation::new( + self.tcx, cause, self.param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(tcx_ty.into())) - .to_predicate(self.tcx), + ty::Binder::dummy(ty::PredicateKind::WellFormed(tcx_ty.into())), ), ); if !errors.is_empty() { diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 6a4a6a5b0a5..139f2e84136 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -4,7 +4,7 @@ use rustc_errors::{Applicability, Diagnostic, MultiSpan}; use rustc_hir::{self as hir, ExprKind}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::traits::Obligation; -use rustc_middle::ty::{self, ToPredicate, Ty}; +use rustc_middle::ty::{self, Ty}; use rustc_span::Span; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{ @@ -538,23 +538,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .bound_explicit_item_bounds(rpit_def_id) .subst_iter_copied(self.tcx, substs) { - let pred = match pred.kind().skip_binder() { + let pred = pred.kind().rebind(match pred.kind().skip_binder() { ty::PredicateKind::Trait(mut trait_pred) => { assert_eq!(trait_pred.trait_ref.self_ty(), opaque_ty); trait_pred.trait_ref.substs = self.tcx.mk_substs_trait(ty, &trait_pred.trait_ref.substs[1..]); - pred.kind().rebind(trait_pred).to_predicate(self.tcx) + ty::PredicateKind::Trait(trait_pred) } ty::PredicateKind::Projection(mut proj_pred) => { assert_eq!(proj_pred.projection_ty.self_ty(), opaque_ty); proj_pred.projection_ty.substs = self .tcx .mk_substs_trait(ty, &proj_pred.projection_ty.substs[1..]); - pred.kind().rebind(proj_pred).to_predicate(self.tcx) + ty::PredicateKind::Projection(proj_pred) } _ => continue, - }; + }); if !self.predicate_must_hold_modulo_regions(&Obligation::new( + self.tcx, ObligationCause::misc(span, self.body_id), self.param_env, pred, diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index ed2218b8746..302d512c71d 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -380,6 +380,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { predicates.predicates.iter().zip(&predicates.spans) { let obligation = Obligation::new( + self.tcx, ObligationCause::dummy_with_span(callee_expr.span), self.param_env, *predicate, diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 1578cddd490..b9e90e47e50 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -102,7 +102,7 @@ pub(super) fn check_fn<'a, 'tcx>( inherited.typeck_results.borrow_mut().liberated_fn_sigs_mut().insert(fn_id, fn_sig); - if let ty::Dynamic(..) = declared_ret_ty.kind() { + if let ty::Dynamic(_, _, ty::Dyn) = declared_ret_ty.kind() { // FIXME: We need to verify that the return type is `Sized` after the return expression has // been evaluated so that we have types available for all the nodes being returned, but that // requires the coerced evaluated type to be stored. Moving `check_return_expr` before this diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 71949b42118..174b4331382 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -55,7 +55,7 @@ use rustc_middle::ty::error::TypeError; use rustc_middle::ty::relate::RelateResult; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::visit::TypeVisitable; -use rustc_middle::ty::{self, ToPredicate, Ty, TypeAndMut}; +use rustc_middle::ty::{self, Ty, TypeAndMut}; use rustc_session::parse::feature_err; use rustc_span::symbol::sym; use rustc_span::{self, BytePos, DesugaringKind, Span}; @@ -278,13 +278,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { for &source_ty in &[a, b] { if source_ty != target_ty { obligations.push(Obligation::new( + self.tcx(), self.cause.clone(), self.param_env, ty::Binder::dummy(ty::PredicateKind::Coerce(ty::CoercePredicate { a: source_ty, b: target_ty, - })) - .to_predicate(self.tcx()), + })), )); } } @@ -669,7 +669,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { continue; } }; - match selcx.select(&obligation.with(trait_pred)) { + match selcx.select(&obligation.with(selcx.tcx(), trait_pred)) { // Uncertain or unimplemented. Ok(None) => { if trait_pred.def_id() == unsize_did { @@ -783,10 +783,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { // and then require that the resulting predicate (e.g., `usize: Clone`) // holds (it does). let predicate = predicate.with_self_ty(self.tcx, a); - Obligation::new(self.cause.clone(), self.param_env, predicate) + Obligation::new(self.tcx, self.cause.clone(), self.param_env, predicate) }) // Enforce the region bound (e.g., `usize: 'static`, in our example). .chain([Obligation::new( + self.tcx, self.cause.clone(), self.param_env, self.tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::TypeOutlives( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 97d05b4f95c..c826a886ca6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -22,8 +22,7 @@ use rustc_middle::ty::error::TypeError; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::{ - self, AdtKind, CanonicalUserType, DefIdTree, EarlyBinder, GenericParamDefKind, ToPredicate, Ty, - UserType, + self, AdtKind, CanonicalUserType, DefIdTree, EarlyBinder, GenericParamDefKind, Ty, UserType, }; use rustc_middle::ty::{GenericArgKind, InternalSubsts, SubstsRef, UserSelfTy, UserSubsts}; use rustc_session::lint; @@ -559,9 +558,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // WF obligations never themselves fail, so no real need to give a detailed cause: let cause = traits::ObligationCause::new(span, self.body_id, code); self.register_predicate(traits::Obligation::new( + self.tcx, cause, self.param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(self.tcx), + ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)), )); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 8cf70eb5431..c3833b4872d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -73,7 +73,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = self.typeck_results.borrow().expr_ty_adjusted(expr); let ty = self.resolve_vars_if_possible(ty); if ty.has_non_region_infer() { - assert!(self.is_tainted_by_errors()); self.tcx.ty_error() } else { self.tcx.erase_regions(ty) @@ -2150,6 +2149,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), ); let obligation = traits::Obligation::new( + self.tcx, traits::ObligationCause::dummy(), self.param_env, ty::Binder::dummy(ty::TraitPredicate { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 06e6e4350fc..316ecb0ed52 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1090,14 +1090,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(into_def_id) = self.tcx.get_diagnostic_item(sym::Into) && self.predicate_must_hold_modulo_regions(&traits::Obligation::new( + self.tcx, self.misc(expr.span), self.param_env, ty::Binder::dummy(ty::TraitRef { def_id: into_def_id, substs: self.tcx.mk_substs_trait(expr_ty, &[expected_ty.into()]), }) - .to_poly_trait_predicate() - .to_predicate(self.tcx), + .to_poly_trait_predicate(), )) { let sugg = if expr.precedence().order() >= PREC_POSTFIX { diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 3f390cba3e7..37336edd1fd 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -20,7 +20,7 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::{self, InferOk}; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; -use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TypeVisitable}; +use rustc_middle::ty::{self, DefIdTree, GenericParamDefKind, Ty, TypeVisitable}; use rustc_span::symbol::Ident; use rustc_span::Span; use rustc_trait_selection::traits; @@ -293,10 +293,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let poly_trait_ref = ty::Binder::dummy(trait_ref); ( traits::Obligation::misc( + self.tcx, span, self.body_id, self.param_env, - poly_trait_ref.without_const().to_predicate(self.tcx), + poly_trait_ref.without_const(), ), substs, ) @@ -335,6 +336,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ( traits::Obligation::new( + self.tcx, traits::ObligationCause::new( span, self.body_id, @@ -346,7 +348,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, ), self.param_env, - poly_trait_ref.without_const().to_predicate(self.tcx), + poly_trait_ref.without_const(), ), substs, ) @@ -523,9 +525,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { method_ty, obligation ); obligations.push(traits::Obligation::new( + tcx, cause, self.param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(method_ty.into())).to_predicate(tcx), + ty::Binder::dummy(ty::PredicateKind::WellFormed(method_ty.into())), )); let callee = MethodCallee { def_id, substs, sig: fn_sig }; diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 46a76085189..9d75ccad133 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -19,7 +19,8 @@ use rustc_middle::middle::stability; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::AssocItem; use rustc_middle::ty::GenericParamDefKind; -use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitable}; +use rustc_middle::ty::ToPredicate; +use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFoldable, TypeVisitable}; use rustc_middle::ty::{InternalSubsts, SubstsRef}; use rustc_session::lint; use rustc_span::def_id::DefId; @@ -1429,7 +1430,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { ) -> traits::SelectionResult<'tcx, traits::Selection<'tcx>> { let cause = traits::ObligationCause::misc(self.span, self.body_id); let predicate = ty::Binder::dummy(trait_ref).to_poly_trait_predicate(); - let obligation = traits::Obligation::new(cause, self.param_env, predicate); + let obligation = traits::Obligation::new(self.tcx, cause, self.param_env, predicate); traits::SelectionContext::new(self).select(&obligation) } @@ -1560,7 +1561,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let predicate = ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx); parent_pred = Some(predicate); - let obligation = traits::Obligation::new(cause, self.param_env, predicate); + let obligation = + traits::Obligation::new(self.tcx, cause, self.param_env, predicate); if !self.predicate_may_hold(&obligation) { result = ProbeResult::NoMatch; if self.probe(|_| { diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 19f56c73823..e2c5edd0e88 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -23,7 +23,7 @@ use rustc_middle::traits::util::supertraits; use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::print::with_crate_prefix; -use rustc_middle::ty::{self, DefIdTree, GenericArgKind, ToPredicate, Ty, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{self, DefIdTree, GenericArgKind, Ty, TyCtxt, TypeVisitable}; use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Symbol; @@ -80,10 +80,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs); let poly_trait_ref = ty::Binder::dummy(trait_ref); let obligation = Obligation::misc( + tcx, span, self.body_id, self.param_env, - poly_trait_ref.without_const().to_predicate(tcx), + poly_trait_ref.without_const(), ); self.predicate_may_hold(&obligation) }) diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index a299a3e578d..34f54328230 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -581,9 +581,9 @@ impl<'tcx> InferCtxt<'tcx> { span_bug!(cause.span, "unexpected const outlives {:?}", predicate); } }; - let predicate = predicate.0.rebind(atom).to_predicate(self.tcx); + let predicate = predicate.0.rebind(atom); - Obligation::new(cause, param_env, predicate) + Obligation::new(self.tcx, cause, param_env, predicate) } /// Given two sets of values for the same set of canonical variables, unify them. diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index a973bf54b05..37f071a19ac 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -37,7 +37,7 @@ use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{self, InferConst, Ty, TyCtxt, TypeVisitable}; use rustc_middle::ty::{IntType, UintType}; use rustc_span::{Span, DUMMY_SP}; @@ -347,10 +347,10 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { if needs_wf { self.obligations.push(Obligation::new( + self.tcx(), self.trace.cause.clone(), self.param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(b_ty.into())) - .to_predicate(self.infcx.tcx), + ty::Binder::dummy(ty::PredicateKind::WellFormed(b_ty.into())), )); } @@ -444,9 +444,10 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> { ty::PredicateKind::ConstEquate(b, a) }; self.obligations.push(Obligation::new( + self.tcx(), self.trace.cause.clone(), self.param_env, - ty::Binder::dummy(predicate).to_predicate(self.tcx()), + ty::Binder::dummy(predicate), )); } } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index a982f11f718..1fa95f8d62a 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -595,7 +595,12 @@ impl<'tcx> InferCtxt<'tcx> { } // Require that the predicate holds for the concrete type. debug!(?predicate); - obligations.push(traits::Obligation::new(cause.clone(), param_env, predicate)); + obligations.push(traits::Obligation::new( + self.tcx, + cause.clone(), + param_env, + predicate, + )); } Ok(InferOk { value: (), obligations }) } diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs index 9f12bc972a8..eb6deee291c 100644 --- a/compiler/rustc_infer/src/infer/projection.rs +++ b/compiler/rustc_infer/src/infer/projection.rs @@ -1,5 +1,5 @@ use rustc_middle::traits::ObligationCause; -use rustc_middle::ty::{self, ToPredicate, Ty}; +use rustc_middle::ty::{self, Ty}; use crate::traits::{Obligation, PredicateObligation}; @@ -28,12 +28,8 @@ impl<'tcx> InferCtxt<'tcx> { }); let projection = ty::Binder::dummy(ty::ProjectionPredicate { projection_ty, term: ty_var.into() }); - let obligation = Obligation::with_depth( - cause, - recursion_depth, - param_env, - projection.to_predicate(self.tcx), - ); + let obligation = + Obligation::with_depth(self.tcx, cause, recursion_depth, param_env, projection); obligations.push(obligation); ty_var } diff --git a/compiler/rustc_infer/src/infer/sub.rs b/compiler/rustc_infer/src/infer/sub.rs index 97354ba5d1b..8c8445a4d9e 100644 --- a/compiler/rustc_infer/src/infer/sub.rs +++ b/compiler/rustc_infer/src/infer/sub.rs @@ -6,7 +6,7 @@ use crate::traits::Obligation; use rustc_middle::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; use rustc_middle::ty::visit::TypeVisitable; use rustc_middle::ty::TyVar; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use std::mem; /// Ensures `a` is made a subtype of `b`. Returns `a` on success. @@ -95,14 +95,14 @@ impl<'tcx> TypeRelation<'tcx> for Sub<'_, '_, 'tcx> { // can't make progress on `A <: B` if both A and B are // type variables, so record an obligation. self.fields.obligations.push(Obligation::new( + self.tcx(), self.fields.trace.cause.clone(), self.fields.param_env, ty::Binder::dummy(ty::PredicateKind::Subtype(ty::SubtypePredicate { a_is_expected: self.a_is_expected, a, b, - })) - .to_predicate(self.tcx()), + })), )); Ok(a) diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index c8600ded987..a9e6241bf6b 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -10,7 +10,7 @@ pub mod util; use rustc_hir as hir; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::{self, Const, Ty, TyCtxt}; +use rustc_middle::ty::{self, Const, ToPredicate, Ty, TyCtxt}; use rustc_span::Span; pub use self::FulfillmentErrorCode::*; @@ -124,38 +124,41 @@ pub enum FulfillmentErrorCode<'tcx> { impl<'tcx, O> Obligation<'tcx, O> { pub fn new( + tcx: TyCtxt<'tcx>, cause: ObligationCause<'tcx>, param_env: ty::ParamEnv<'tcx>, - predicate: O, + predicate: impl ToPredicate<'tcx, O>, ) -> Obligation<'tcx, O> { - Obligation { cause, param_env, recursion_depth: 0, predicate } + Self::with_depth(tcx, cause, 0, param_env, predicate) } pub fn with_depth( + tcx: TyCtxt<'tcx>, cause: ObligationCause<'tcx>, recursion_depth: usize, param_env: ty::ParamEnv<'tcx>, - predicate: O, + predicate: impl ToPredicate<'tcx, O>, ) -> Obligation<'tcx, O> { + let predicate = predicate.to_predicate(tcx); Obligation { cause, param_env, recursion_depth, predicate } } pub fn misc( + tcx: TyCtxt<'tcx>, span: Span, body_id: hir::HirId, param_env: ty::ParamEnv<'tcx>, - trait_ref: O, + trait_ref: impl ToPredicate<'tcx, O>, ) -> Obligation<'tcx, O> { - Obligation::new(ObligationCause::misc(span, body_id), param_env, trait_ref) + Obligation::new(tcx, ObligationCause::misc(span, body_id), param_env, trait_ref) } - pub fn with

(&self, value: P) -> Obligation<'tcx, P> { - Obligation { - cause: self.cause.clone(), - param_env: self.param_env, - recursion_depth: self.recursion_depth, - predicate: value, - } + pub fn with

( + &self, + tcx: TyCtxt<'tcx>, + value: impl ToPredicate<'tcx, P>, + ) -> Obligation<'tcx, P> { + Obligation::with_depth(tcx, self.cause.clone(), self.recursion_depth, self.param_env, value) } } diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 619582c0539..7e0a8a0df16 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -108,6 +108,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { // then we must've taken advantage of the hack in `project_and_unify_types` where // we replace opaques with inference vars. Emit a warning! if !infcx.predicate_must_hold_modulo_regions(&traits::Obligation::new( + cx.tcx, traits::ObligationCause::dummy(), cx.param_env, assoc_pred, diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index ff0fb9bae92..9ae34013ecb 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -533,16 +533,14 @@ trait UnusedDelimLint { right_pos: Option, ) { let spans = match value.kind { - ast::ExprKind::Block(ref block, None) if block.stmts.len() > 0 => { - let start = block.stmts[0].span; - let end = block.stmts[block.stmts.len() - 1].span; - if let Some(start) = start.find_ancestor_inside(value.span) - && let Some(end) = end.find_ancestor_inside(value.span) + ast::ExprKind::Block(ref block, None) if block.stmts.len() == 1 => { + if let StmtKind::Expr(expr) = &block.stmts[0].kind + && let ExprKind::Err = expr.kind { - Some(( - value.span.with_hi(start.lo()), - value.span.with_lo(end.hi()), - )) + return + } + if let Some(span) = block.stmts[0].span.find_ancestor_inside(value.span) { + Some((value.span.with_hi(span.lo()), value.span.with_lo(span.hi()))) } else { None } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 05382bd887c..1890c0e24bb 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -924,10 +924,13 @@ impl ObjectSafetyViolation { } ObjectSafetyViolation::Method( name, - MethodViolationCode::ReferencesImplTraitInTrait, + MethodViolationCode::ReferencesImplTraitInTrait(_), _, ) => format!("method `{}` references an `impl Trait` type in its return type", name) .into(), + ObjectSafetyViolation::Method(name, MethodViolationCode::AsyncFn, _) => { + format!("method `{}` is `async`", name).into() + } ObjectSafetyViolation::Method( name, MethodViolationCode::WhereClauseReferencesSelf, @@ -1035,7 +1038,10 @@ pub enum MethodViolationCode { ReferencesSelfOutput, /// e.g., `fn foo(&self) -> impl Sized` - ReferencesImplTraitInTrait, + ReferencesImplTraitInTrait(Span), + + /// e.g., `async fn foo(&self)` + AsyncFn, /// e.g., `fn foo(&self) where Self: Clone` WhereClauseReferencesSelf, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 18eb06b83c9..f9a762261e2 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1125,42 +1125,42 @@ impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { } } -pub trait ToPredicate<'tcx> { - fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx>; +pub trait ToPredicate<'tcx, Predicate> { + fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate; } -impl<'tcx> ToPredicate<'tcx> for Predicate<'tcx> { - fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { +impl<'tcx, T> ToPredicate<'tcx, T> for T { + fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> T { self } } -impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> { +impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for Binder<'tcx, PredicateKind<'tcx>> { #[inline(always)] fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { tcx.mk_predicate(self) } } -impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> { +impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyTraitPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.map_bound(PredicateKind::Trait).to_predicate(tcx) } } -impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> { +impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyRegionOutlivesPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.map_bound(PredicateKind::RegionOutlives).to_predicate(tcx) } } -impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> { +impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyTypeOutlivesPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.map_bound(PredicateKind::TypeOutlives).to_predicate(tcx) } } -impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { +impl<'tcx> ToPredicate<'tcx, Predicate<'tcx>> for PolyProjectionPredicate<'tcx> { fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> { self.map_bound(PredicateKind::Projection).to_predicate(tcx) } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a56450a3573..02848bcffb2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -893,6 +893,7 @@ symbols! { masked, match_beginning_vert, match_default_bindings, + matches_macro, maxnumf32, maxnumf64, may_dangle, diff --git a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs index 2cf2cbc7510..52ee68e7560 100644 --- a/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/arm64_32_apple_watchos.rs @@ -12,6 +12,8 @@ pub fn target() -> Target { features: "+neon,+fp-armv8,+apple-a7".into(), max_atomic_width: Some(128), forces_embed_bitcode: true, + dynamic_linking: false, + position_independent_executables: true, // These arguments are not actually invoked - they just have // to look right to pass App Store validation. bitcode_llvm_cmdline: "-triple\0\ diff --git a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs index 45ead8d65ab..6e1d00d1f6c 100644 --- a/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs +++ b/compiler/rustc_target/src/spec/armv7k_apple_watchos.rs @@ -12,6 +12,8 @@ pub fn target() -> Target { features: "+v7,+vfp4,+neon".into(), max_atomic_width: Some(64), forces_embed_bitcode: true, + dynamic_linking: false, + position_independent_executables: true, // These arguments are not actually invoked - they just have // to look right to pass App Store validation. bitcode_llvm_cmdline: "-triple\0\ diff --git a/compiler/rustc_trait_selection/src/autoderef.rs b/compiler/rustc_trait_selection/src/autoderef.rs index 54c738d8389..b7240a82897 100644 --- a/compiler/rustc_trait_selection/src/autoderef.rs +++ b/compiler/rustc_trait_selection/src/autoderef.rs @@ -3,8 +3,8 @@ use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::{self, TraitEngine, TraitEngineExt}; use rustc_hir as hir; use rustc_infer::infer::InferCtxt; +use rustc_middle::ty::TypeVisitable; use rustc_middle::ty::{self, TraitRef, Ty, TyCtxt}; -use rustc_middle::ty::{ToPredicate, TypeVisitable}; use rustc_session::Limit; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::Span; @@ -130,9 +130,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> { let cause = traits::ObligationCause::misc(self.span, self.body_id); let obligation = traits::Obligation::new( + tcx, cause.clone(), self.param_env, - ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx), + ty::Binder::dummy(trait_ref).without_const(), ); if !self.infcx.predicate_may_hold(&obligation) { debug!("overloaded_deref_ty: cannot match obligation"); diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 188f8bb7e2a..5869bc76b59 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -96,8 +96,12 @@ impl<'tcx> AutoTraitFinder<'tcx> { PolyTraitRef::to_poly_trait_predicate, PolyTraitRef::to_poly_trait_predicate_negative_polarity, ] { - let result = - selcx.select(&Obligation::new(ObligationCause::dummy(), orig_env, f(&trait_pred))); + let result = selcx.select(&Obligation::new( + tcx, + ObligationCause::dummy(), + orig_env, + f(&trait_pred), + )); if let Ok(Some(ImplSource::UserDefined(_))) = result { debug!( "find_auto_trait_generics({:?}): \ @@ -280,8 +284,12 @@ impl<'tcx> AutoTraitFinder<'tcx> { // Call `infcx.resolve_vars_if_possible` to see if we can // get rid of any inference variables. - let obligation = - infcx.resolve_vars_if_possible(Obligation::new(dummy_cause.clone(), new_env, pred)); + let obligation = infcx.resolve_vars_if_possible(Obligation::new( + tcx, + dummy_cause.clone(), + new_env, + pred, + )); let result = select.select(&obligation); match result { @@ -706,7 +714,10 @@ impl<'tcx> AutoTraitFinder<'tcx> { // and turn them into an explicit negative impl for our type. debug!("Projecting and unifying projection predicate {:?}", predicate); - match project::poly_project_and_unify_type(select, &obligation.with(p)) { + match project::poly_project_and_unify_type( + select, + &obligation.with(self.tcx, p), + ) { ProjectAndUnifyResult::MismatchedProjectionTypes(e) => { debug!( "evaluate_nested_obligations: Unable to unify predicate \ diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_trait_selection/src/traits/codegen.rs index 8a62bf01567..ca4299f7db3 100644 --- a/compiler/rustc_trait_selection/src/traits/codegen.rs +++ b/compiler/rustc_trait_selection/src/traits/codegen.rs @@ -40,7 +40,7 @@ pub fn codegen_select_candidate<'tcx>( let obligation_cause = ObligationCause::dummy(); let obligation = - Obligation::new(obligation_cause, param_env, trait_ref.to_poly_trait_predicate()); + Obligation::new(tcx, obligation_cause, param_env, trait_ref.to_poly_trait_predicate()); let selection = match selcx.select(&obligation) { Ok(Some(selection)) => selection, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs index 58da54afb75..6a5744f5f76 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs @@ -32,7 +32,7 @@ pub fn recompute_applicable_impls<'tcx>( impl_predicates .predicates .iter() - .map(|&predicate| Obligation::new(dummy_cause.clone(), param_env, predicate)), + .map(|&predicate| Obligation::new(tcx, dummy_cause.clone(), param_env, predicate)), ); ocx.select_where_possible().is_empty() diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 786cadaa6ce..f087afa20ba 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -344,14 +344,14 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { }); let substs = self.tcx.mk_substs_trait(ty.skip_binder(), &[var.into()]); let obligation = Obligation::new( + self.tcx, ObligationCause::dummy(), param_env, ty.rebind(ty::TraitPredicate { trait_ref: ty::TraitRef::new(trait_def_id, substs), constness, polarity, - }) - .to_predicate(self.tcx), + }), ); let mut fulfill_cx = >::new_in_snapshot(self.tcx); fulfill_cx.register_predicate_obligation(self, obligation); @@ -984,7 +984,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ); trait_pred }); - let unit_obligation = obligation.with(predicate.to_predicate(tcx)); + let unit_obligation = obligation.with(tcx, predicate); if self.predicate_may_hold(&unit_obligation) { err.note( "this error might have been caused by changes to \ @@ -2012,7 +2012,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ..*tr }); - Obligation::new(ObligationCause::dummy(), param_env, trait_pred.to_predicate(self.tcx)) + Obligation::new(self.tcx, ObligationCause::dummy(), param_env, trait_pred) } #[instrument(skip(self), level = "debug")] @@ -2100,11 +2100,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) }; - let obligation = Obligation::new( - obligation.cause.clone(), - obligation.param_env, - trait_ref.to_poly_trait_predicate(), - ); + let obligation = obligation.with(self.tcx, trait_ref.to_poly_trait_predicate()); let mut selcx = SelectionContext::with_query_mode( &self, crate::traits::TraitQueryMode::Standard, @@ -2534,11 +2530,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) .value; - let obligation = Obligation::new( - ObligationCause::dummy(), - param_env, - cleaned_pred.to_predicate(selcx.tcx()), - ); + let obligation = + Obligation::new(self.tcx, ObligationCause::dummy(), param_env, cleaned_pred); self.predicate_may_hold(&obligation) }) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 84daaf97ecf..b8609077036 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -301,7 +301,7 @@ pub trait TypeErrCtxtExt<'tcx> { obligated_types: &mut Vec>, seen_requirements: &mut FxHashSet, ) where - T: fmt::Display; + T: fmt::Display + ToPredicate<'tcx, T>; /// Suggest to await before try: future? => future.await? fn suggest_await_before_try( @@ -334,7 +334,7 @@ pub trait TypeErrCtxtExt<'tcx> { ); } -fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, String) { +fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) { ( generics.tail_span_for_predicate_suggestion(), format!("{} {}", generics.add_where_or_trailing_comma(), pred), @@ -416,7 +416,7 @@ fn suggest_restriction<'tcx>( }, // `fn foo(t: impl Trait)` // ^ suggest `where ::A: Bound` - predicate_constraint(hir_generics, trait_pred.to_predicate(tcx).to_string()), + predicate_constraint(hir_generics, trait_pred.to_predicate(tcx)), ]; sugg.extend(ty_spans.into_iter().map(|s| (s, type_param_name.to_string()))); @@ -440,9 +440,7 @@ fn suggest_restriction<'tcx>( .find(|p| !matches!(p.kind, hir::GenericParamKind::Type { synthetic: true, .. })), super_traits, ) { - (_, None) => { - predicate_constraint(hir_generics, trait_pred.to_predicate(tcx).to_string()) - } + (_, None) => predicate_constraint(hir_generics, trait_pred.to_predicate(tcx)), (None, Some((ident, []))) => ( ident.span.shrink_to_hi(), format!(": {}", trait_pred.print_modifiers_and_trait_path()), @@ -1162,7 +1160,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { for predicate in predicates.iter() { if !self.predicate_must_hold_modulo_regions( - &obligation.with(predicate.with_self_ty(self.tcx, self_ref_ty)), + &obligation.with(self.tcx, predicate.with_self_ty(self.tcx, self_ref_ty)), ) { return; } @@ -1523,7 +1521,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { let self_ty_satisfies_dyn_predicates = |self_ty| { predicates.iter().all(|predicate| { let pred = predicate.with_self_ty(self.tcx, self_ty); - let obl = Obligation::new(cause.clone(), param_env, pred); + let obl = Obligation::new(self.tcx, cause.clone(), param_env, pred); self.predicate_may_hold(&obl) }) }; @@ -2704,7 +2702,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { obligated_types.push(ty); - let parent_predicate = parent_trait_ref.to_predicate(tcx); + let parent_predicate = parent_trait_ref; if !self.is_recursive_obligation(obligated_types, &data.parent_code) { // #74711: avoid a stack overflow ensure_sufficient_stack(|| { @@ -2766,7 +2764,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { _ => err.note(&msg), }; - let mut parent_predicate = parent_trait_pred.to_predicate(tcx); + let mut parent_predicate = parent_trait_pred; let mut data = &data.derived; let mut count = 0; seen_requirements.insert(parent_def_id); @@ -2826,7 +2824,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } ObligationCauseCode::DerivedObligation(ref data) => { let parent_trait_ref = self.resolve_vars_if_possible(data.parent_trait_pred); - let parent_predicate = parent_trait_ref.to_predicate(tcx); + let parent_predicate = parent_trait_ref; // #74711: avoid a stack overflow ensure_sufficient_stack(|| { self.note_obligation_cause_code( @@ -3070,9 +3068,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ..*tr }); let field_obl = Obligation::new( + self.tcx, obligation.cause.clone(), obligation.param_env, - trait_pred.to_predicate(self.tcx), + trait_pred, ); self.predicate_must_hold_modulo_regions(&field_obl) }) diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 4905bb69cc5..d84f768cce4 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -9,7 +9,6 @@ use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::abstract_const::NotConstEvaluatable; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::subst::SubstsRef; -use rustc_middle::ty::ToPredicate; use rustc_middle::ty::{self, Binder, Const, Ty, TypeVisitable}; use std::marker::PhantomData; @@ -296,7 +295,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { &mut obligations, ); if predicate != obligation.predicate { - obligations.push(obligation.with(predicate)); + obligations.push(obligation.with(infcx.tcx, predicate)); return ProcessResult::Changed(mk_pending(obligations)); } } @@ -307,7 +306,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { // This means we need to pass it the bound version of our // predicate. ty::PredicateKind::Trait(trait_ref) => { - let trait_obligation = obligation.with(binder.rebind(trait_ref)); + let trait_obligation = obligation.with(infcx.tcx, binder.rebind(trait_ref)); self.process_trait_obligation( obligation, @@ -316,7 +315,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { ) } ty::PredicateKind::Projection(data) => { - let project_obligation = obligation.with(binder.rebind(data)); + let project_obligation = obligation.with(infcx.tcx, binder.rebind(data)); self.process_projection_obligation( obligation, @@ -335,9 +334,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { | ty::PredicateKind::ConstEquate(..) => { let pred = ty::Binder::dummy(infcx.replace_bound_vars_with_placeholders(binder)); - ProcessResult::Changed(mk_pending(vec![ - obligation.with(pred.to_predicate(self.selcx.tcx())), - ])) + ProcessResult::Changed(mk_pending(vec![obligation.with(infcx.tcx, pred)])) } ty::PredicateKind::TypeWellFormedFromEnv(..) => { bug!("TypeWellFormedFromEnv is only used for Chalk") @@ -345,7 +342,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { }, Some(pred) => match pred { ty::PredicateKind::Trait(data) => { - let trait_obligation = obligation.with(Binder::dummy(data)); + let trait_obligation = obligation.with(infcx.tcx, Binder::dummy(data)); self.process_trait_obligation( obligation, @@ -370,7 +367,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { } ty::PredicateKind::Projection(ref data) => { - let project_obligation = obligation.with(Binder::dummy(*data)); + let project_obligation = obligation.with(infcx.tcx, Binder::dummy(*data)); self.process_projection_obligation( obligation, @@ -697,7 +694,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { } // Let the caller handle the recursion ProjectAndUnifyResult::Recursive => ProcessResult::Changed(mk_pending(vec![ - project_obligation.with(project_obligation.predicate.to_predicate(tcx)), + project_obligation.with(tcx, project_obligation.predicate), ])), ProjectAndUnifyResult::MismatchedProjectionTypes(e) => { ProcessResult::Error(CodeProjectionError(e)) diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 10e48610e3a..ddc9b768f07 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -440,7 +440,7 @@ pub fn impossible_predicates<'tcx>( let ocx = ObligationCtxt::new(&infcx); let predicates = ocx.normalize(ObligationCause::dummy(), param_env, predicates); for predicate in predicates { - let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate); + let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate); ocx.register_obligation(obligation); } let errors = ocx.select_all_or_error(); @@ -530,6 +530,7 @@ fn is_impossible_method<'tcx>( let predicates_for_trait = predicates.predicates.iter().filter_map(|(pred, span)| { if pred.visit_with(&mut visitor).is_continue() { Some(Obligation::new( + tcx, ObligationCause::dummy_with_span(*span), param_env, ty::EarlyBinder(*pred).subst(tcx, impl_trait_ref.substs), diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 0bb25a74dc8..9745e0137ee 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -375,6 +375,7 @@ fn object_safety_violation_for_method( let span = match (&v, node) { (MethodViolationCode::ReferencesSelfInput(Some(span)), _) => *span, (MethodViolationCode::UndispatchableReceiver(Some(span)), _) => *span, + (MethodViolationCode::ReferencesImplTraitInTrait(span), _) => *span, (MethodViolationCode::ReferencesSelfOutput, Some(node)) => { node.fn_decl().map_or(method.ident(tcx).span, |decl| decl.output.span()) } @@ -437,8 +438,8 @@ fn virtual_call_violation_for_method<'tcx>( if contains_illegal_self_type_reference(tcx, trait_def_id, sig.output()) { return Some(MethodViolationCode::ReferencesSelfOutput); } - if contains_illegal_impl_trait_in_trait(tcx, sig.output()) { - return Some(MethodViolationCode::ReferencesImplTraitInTrait); + if let Some(code) = contains_illegal_impl_trait_in_trait(tcx, method.def_id, sig.output()) { + return Some(code); } // We can't monomorphize things like `fn foo(...)`. @@ -723,10 +724,9 @@ fn receiver_is_dispatchable<'tcx>( def_id: dispatch_from_dyn_did, substs: tcx.mk_substs_trait(receiver_ty, &[unsized_receiver_ty.into()]), }) - .without_const() - .to_predicate(tcx); + .without_const(); - Obligation::new(ObligationCause::dummy(), param_env, predicate) + Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate) }; let infcx = tcx.infer_ctxt().build(); @@ -865,16 +865,24 @@ fn contains_illegal_self_type_reference<'tcx, T: TypeVisitable<'tcx>>( pub fn contains_illegal_impl_trait_in_trait<'tcx>( tcx: TyCtxt<'tcx>, + fn_def_id: DefId, ty: ty::Binder<'tcx, Ty<'tcx>>, -) -> bool { +) -> Option { + // This would be caught below, but rendering the error as a separate + // `async-specific` message is better. + if tcx.asyncness(fn_def_id).is_async() { + return Some(MethodViolationCode::AsyncFn); + } + // FIXME(RPITIT): Perhaps we should use a visitor here? - ty.skip_binder().walk().any(|arg| { + ty.skip_binder().walk().find_map(|arg| { if let ty::GenericArgKind::Type(ty) = arg.unpack() && let ty::Projection(proj) = ty.kind() + && tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder { - tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder + Some(MethodViolationCode::ReferencesImplTraitInTrait(tcx.def_span(proj.item_def_id))) } else { - false + None } }) } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 572f82117cc..ede6cd607b7 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -200,7 +200,7 @@ pub(super) fn poly_project_and_unify_type<'cx, 'tcx>( infcx.replace_bound_vars_with_placeholders(obligation.predicate); let new_universe = infcx.universe(); - let placeholder_obligation = obligation.with(placeholder_predicate); + let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate); match project_and_unify_type(selcx, &placeholder_obligation) { ProjectAndUnifyResult::MismatchedProjectionTypes(e) => Err(e), ProjectAndUnifyResult::Holds(obligations) @@ -517,6 +517,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { let recursion_limit = self.tcx().recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { let obligation = Obligation::with_depth( + self.tcx(), self.cause.clone(), recursion_limit.0, self.param_env, @@ -573,6 +574,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { && !self.tcx().sess.opts.actually_rustdoc { let obligation = Obligation::with_depth( + self.selcx.tcx(), self.cause.clone(), recursion_limit.0, self.param_env, @@ -1110,7 +1112,8 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( } } - let obligation = Obligation::with_depth(cause.clone(), depth, param_env, projection_ty); + let obligation = + Obligation::with_depth(selcx.tcx(), cause.clone(), depth, param_env, projection_ty); match project(selcx, &obligation) { Ok(Projected::Progress(Progress { @@ -1343,8 +1346,8 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>( ty::Binder::dummy(ty::TraitRef { def_id: trait_def_id, substs: trait_substs }) .to_poly_trait_predicate(); - let _ = - selcx.infcx().commit_if_ok(|_| match selcx.select(&obligation.with(trait_predicate)) { + let _ = selcx.infcx().commit_if_ok(|_| { + match selcx.select(&obligation.with(tcx, trait_predicate)) { Ok(Some(super::ImplSource::UserDefined(data))) => { candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait( ImplTraitInTraitCandidate::Impl(data), @@ -1364,7 +1367,8 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>( candidate_set.mark_error(e); return Err(()); } - }); + } + }); } } @@ -1538,7 +1542,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // If we are resolving `>::Item == Type`, // start out by selecting the predicate `T as TraitRef<...>`: let poly_trait_ref = ty::Binder::dummy(obligation.predicate.trait_ref(selcx.tcx())); - let trait_obligation = obligation.with(poly_trait_ref.to_poly_trait_predicate()); + let trait_obligation = obligation.with(selcx.tcx(), poly_trait_ref.to_poly_trait_predicate()); let _ = selcx.infcx().commit_if_ok(|_| { let impl_source = match selcx.select(&trait_obligation) { Ok(Some(impl_source)) => impl_source, @@ -1705,12 +1709,12 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( ty::Param(_) | ty::Projection(..) | ty::Opaque(..) if selcx.infcx().predicate_must_hold_modulo_regions( &obligation.with( + selcx.tcx(), ty::Binder::dummy(ty::TraitRef::new( selcx.tcx().require_lang_item(LangItem::Sized, None), selcx.tcx().mk_substs_trait(self_ty, &[]), )) - .without_const() - .to_predicate(selcx.tcx()), + .without_const(), ), ) => { @@ -1966,13 +1970,8 @@ fn confirm_pointee_candidate<'cx, 'tcx>( tcx.require_lang_item(LangItem::Sized, None), tcx.mk_substs_trait(self_ty, &[]), )) - .without_const() - .to_predicate(tcx); - obligations.push(Obligation::new( - obligation.cause.clone(), - obligation.param_env, - sized_predicate, - )); + .without_const(); + obligations.push(obligation.with(tcx, sized_predicate)); } let substs = tcx.mk_substs([self_ty.into()].iter()); @@ -2289,6 +2288,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( obligations.extend(std::iter::zip(predicates.predicates, predicates.spans).map( |(pred, span)| { Obligation::with_depth( + tcx, ObligationCause::new( obligation.cause.span, obligation.cause.body_id, @@ -2342,6 +2342,7 @@ fn assoc_ty_own_obligations<'cx, 'tcx>( nested, ); nested.push(Obligation::with_depth( + tcx, obligation.cause.clone(), obligation.recursion_depth + 1, obligation.param_env, diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index a7932b332c9..f5c98558a25 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -208,6 +208,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { let recursion_limit = self.tcx().recursion_limit(); if !recursion_limit.value_within_limit(self.anon_depth) { let obligation = Obligation::with_depth( + self.tcx(), self.cause.clone(), recursion_limit.0, self.param_env, diff --git a/compiler/rustc_trait_selection/src/traits/relationships.rs b/compiler/rustc_trait_selection/src/traits/relationships.rs index 8cf500a466b..dfe19a5a86d 100644 --- a/compiler/rustc_trait_selection/src/traits/relationships.rs +++ b/compiler/rustc_trait_selection/src/traits/relationships.rs @@ -1,8 +1,8 @@ use crate::infer::InferCtxt; use crate::traits::query::evaluate_obligation::InferCtxtExt; -use crate::traits::{ObligationCause, PredicateObligation}; +use crate::traits::PredicateObligation; use rustc_infer::traits::TraitEngine; -use rustc_middle::ty::{self, ToPredicate}; +use rustc_middle::ty; pub(crate) fn update<'tcx, T>( engine: &mut T, @@ -25,9 +25,7 @@ pub(crate) fn update<'tcx, T>( // Then construct a new obligation with Self = () added // to the ParamEnv, and see if it holds. - let o = rustc_infer::traits::Obligation::new( - ObligationCause::dummy(), - obligation.param_env, + let o = obligation.with(infcx.tcx, obligation .predicate .kind() @@ -38,8 +36,7 @@ pub(crate) fn update<'tcx, T>( constness: tpred.constness, polarity: tpred.polarity, }) - ) - .to_predicate(infcx.tcx), + ), ); // Don't report overflow errors. Otherwise equivalent to may_hold. if let Ok(result) = infcx.probe(|_| infcx.evaluate_obligation(&o)) && result.may_apply() { diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 3671a0d87df..3995ea58db1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -13,7 +13,7 @@ use rustc_infer::traits::ObligationCause; use rustc_infer::traits::{Obligation, SelectionError, TraitObligation}; use rustc_lint_defs::builtin::DEREF_INTO_DYN_SUPERTRAIT; use rustc_middle::ty::print::with_no_trimmed_paths; -use rustc_middle::ty::{self, ToPredicate, Ty, TypeVisitable}; +use rustc_middle::ty::{self, Ty, TypeVisitable}; use rustc_target::spec::abi::Abi; use crate::traits; @@ -718,9 +718,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }; let obligation = traits::Obligation::new( + tcx, cause.clone(), param_env, - ty::Binder::dummy(trait_ref).without_const().to_predicate(tcx), + ty::Binder::dummy(trait_ref).without_const(), ); if !self.infcx.predicate_may_hold(&obligation) { return None; diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 28b4bae7cbe..9d43f72b85f 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -194,6 +194,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut obligations, ); obligations.push(Obligation::with_depth( + self.tcx(), obligation.cause.clone(), obligation.recursion_depth + 1, obligation.param_env, @@ -482,11 +483,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { super_trait, &mut nested, ); - nested.push(Obligation::new( - obligation.cause.clone(), - obligation.param_env, - normalized_super_trait, - )); + nested.push(obligation.with(tcx, normalized_super_trait)); } let assoc_types: Vec<_> = tcx @@ -581,11 +578,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { subst_bound, &mut nested, ); - nested.push(Obligation::new( - obligation.cause.clone(), - obligation.param_env, - normalized_bound, - )); + nested.push(obligation.with(tcx, normalized_bound)); } } @@ -644,9 +637,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.tcx().mk_substs_trait(output_ty, &[]), )); nested.push(Obligation::new( + self.infcx.tcx, cause, obligation.param_env, - tr.to_poly_trait_predicate().to_predicate(self.tcx()), + tr.to_poly_trait_predicate(), )); Ok(ImplSourceFnPointerData { fn_ty: self_ty, nested }) @@ -727,11 +721,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // FIXME: Chalk if !self.tcx().sess.opts.unstable_opts.chalk { - nested.push(Obligation::new( - obligation.cause.clone(), - obligation.param_env, - ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind)) - .to_predicate(self.tcx()), + nested.push(obligation.with( + self.tcx(), + ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind)), )); } @@ -860,10 +852,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); let outlives = ty::OutlivesPredicate(r_a, r_b); nested.push(Obligation::with_depth( + tcx, cause, obligation.recursion_depth + 1, obligation.param_env, - obligation.predicate.rebind(outlives).to_predicate(tcx), + obligation.predicate.rebind(outlives), )); } _ => bug!(), @@ -957,10 +950,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ); let outlives = ty::OutlivesPredicate(r_a, r_b); nested.push(Obligation::with_depth( + tcx, cause, obligation.recursion_depth + 1, obligation.param_env, - obligation.predicate.rebind(outlives).to_predicate(tcx), + obligation.predicate.rebind(outlives), )); } @@ -979,6 +973,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let predicate_to_obligation = |predicate| { Obligation::with_depth( + tcx, cause.clone(), obligation.recursion_depth + 1, obligation.param_env, @@ -1255,20 +1250,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.param_env, cause.clone(), obligation.recursion_depth + 1, - self_ty - .rebind(ty::TraitPredicate { - trait_ref: ty::TraitRef { - def_id: self.tcx().require_lang_item(LangItem::Destruct, None), - substs: self.tcx().mk_substs_trait(nested_ty, &[]), - }, - constness: ty::BoundConstness::ConstIfConst, - polarity: ty::ImplPolarity::Positive, - }) - .to_predicate(tcx), + self_ty.rebind(ty::TraitPredicate { + trait_ref: ty::TraitRef { + def_id: self.tcx().require_lang_item(LangItem::Destruct, None), + substs: self.tcx().mk_substs_trait(nested_ty, &[]), + }, + constness: ty::BoundConstness::ConstIfConst, + polarity: ty::ImplPolarity::Positive, + }), &mut nested, ); nested.push(Obligation::with_depth( + tcx, cause.clone(), obligation.recursion_depth + 1, obligation.param_env, @@ -1280,18 +1274,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // since it's either not `const Drop` (and we raise an error during selection), // or it's an ADT (and we need to check for a custom impl during selection) _ => { - let predicate = self_ty - .rebind(ty::TraitPredicate { - trait_ref: ty::TraitRef { - def_id: self.tcx().require_lang_item(LangItem::Destruct, None), - substs: self.tcx().mk_substs_trait(nested_ty, &[]), - }, - constness: ty::BoundConstness::ConstIfConst, - polarity: ty::ImplPolarity::Positive, - }) - .to_predicate(tcx); + let predicate = self_ty.rebind(ty::TraitPredicate { + trait_ref: ty::TraitRef { + def_id: self.tcx().require_lang_item(LangItem::Destruct, None), + substs: self.tcx().mk_substs_trait(nested_ty, &[]), + }, + constness: ty::BoundConstness::ConstIfConst, + polarity: ty::ImplPolarity::Positive, + }); nested.push(Obligation::with_depth( + tcx, cause.clone(), obligation.recursion_depth + 1, obligation.param_env, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 3a899c03b4c..c369c5de52b 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -445,7 +445,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::PredicateKind::Trait(t) => { let t = bound_predicate.rebind(t); debug_assert!(!t.has_escaping_bound_vars()); - let obligation = obligation.with(t); + let obligation = obligation.with(self.tcx(), t); self.evaluate_trait_predicate_recursively(previous_stack, obligation) } @@ -596,7 +596,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::PredicateKind::Projection(data) => { let data = bound_predicate.rebind(data); - let project_obligation = obligation.with(data); + let project_obligation = obligation.with(self.tcx(), data); match project::poly_project_and_unify_type(self, &project_obligation) { ProjectAndUnifyResult::Holds(mut subobligations) => { 'compute_res: { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index fc0a9f69003..d05e893de43 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -4,7 +4,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable}; use rustc_span::Span; use std::iter; @@ -324,7 +324,7 @@ impl<'tcx> WfPredicates<'tcx> { extend_cause_with_original_assoc_item_obligation( tcx, trait_ref, item, &mut cause, predicate, ); - traits::Obligation::with_depth(cause, depth, param_env, predicate) + traits::Obligation::with_depth(tcx, cause, depth, param_env, predicate) }; if let Elaborate::All = elaborate { @@ -356,10 +356,11 @@ impl<'tcx> WfPredicates<'tcx> { } } traits::Obligation::with_depth( + tcx, cause, depth, param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(tcx), + ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)), ) }), ); @@ -407,10 +408,11 @@ impl<'tcx> WfPredicates<'tcx> { .filter(|arg| !arg.has_escaping_bound_vars()) .map(|arg| { traits::Obligation::with_depth( + tcx, cause.clone(), depth, param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(tcx), + ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)), ) }), ); @@ -424,10 +426,11 @@ impl<'tcx> WfPredicates<'tcx> { substs: self.tcx.mk_substs_trait(subty, &[]), }; self.out.push(traits::Obligation::with_depth( + self.tcx, cause, self.recursion_depth, self.param_env, - ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx), + ty::Binder::dummy(trait_ref).without_const(), )); } } @@ -454,10 +457,10 @@ impl<'tcx> WfPredicates<'tcx> { self.out.extend(obligations); let predicate = - ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct)) - .to_predicate(self.tcx()); + ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct)); let cause = self.cause(traits::WellFormed(None)); self.out.push(traits::Obligation::with_depth( + self.tcx(), cause, self.recursion_depth, self.param_env, @@ -468,11 +471,11 @@ impl<'tcx> WfPredicates<'tcx> { let cause = self.cause(traits::WellFormed(None)); self.out.push(traits::Obligation::with_depth( + self.tcx(), cause, self.recursion_depth, self.param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into())) - .to_predicate(self.tcx()), + ty::Binder::dummy(ty::PredicateKind::WellFormed(ct.into())), )); } ty::ConstKind::Error(_) @@ -556,13 +559,13 @@ impl<'tcx> WfPredicates<'tcx> { if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() { let cause = self.cause(traits::ReferenceOutlivesReferent(ty)); self.out.push(traits::Obligation::with_depth( + self.tcx(), cause, depth, param_env, ty::Binder::dummy(ty::PredicateKind::TypeOutlives( ty::OutlivesPredicate(rty, r), - )) - .to_predicate(self.tcx()), + )), )); } } @@ -656,11 +659,11 @@ impl<'tcx> WfPredicates<'tcx> { let tcx = self.tcx(); self.out.extend(component_traits.map(|did| { traits::Obligation::with_depth( + tcx, cause.clone(), depth, param_env, - ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did)) - .to_predicate(tcx), + ty::Binder::dummy(ty::PredicateKind::ObjectSafe(did)), ) })); } @@ -681,11 +684,11 @@ impl<'tcx> WfPredicates<'tcx> { ty::Infer(_) => { let cause = self.cause(traits::WellFormed(None)); self.out.push(traits::Obligation::with_depth( + self.tcx(), cause, self.recursion_depth, param_env, - ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())) - .to_predicate(self.tcx()), + ty::Binder::dummy(ty::PredicateKind::WellFormed(ty.into())), )); } } @@ -724,7 +727,13 @@ impl<'tcx> WfPredicates<'tcx> { if remap_constness { pred = pred.without_const(self.tcx); } - traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred) + traits::Obligation::with_depth( + self.tcx, + cause, + self.recursion_depth, + self.param_env, + pred, + ) }) .filter(|pred| !pred.has_escaping_bound_vars()) .collect() @@ -794,10 +803,11 @@ impl<'tcx> WfPredicates<'tcx> { let outlives = ty::Binder::dummy(ty::OutlivesPredicate(explicit_bound, implicit_bound)); self.out.push(traits::Obligation::with_depth( + self.tcx, cause, self.recursion_depth, self.param_env, - outlives.to_predicate(self.tcx), + outlives, )); } } diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs index 493d5de0807..e94c8efe69a 100644 --- a/compiler/rustc_traits/src/evaluate_obligation.rs +++ b/compiler/rustc_traits/src/evaluate_obligation.rs @@ -26,7 +26,7 @@ fn evaluate_obligation<'tcx>( let ParamEnvAnd { param_env, value: predicate } = goal; let mut selcx = SelectionContext::with_query_mode(&infcx, TraitQueryMode::Canonical); - let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate); + let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, predicate); selcx.evaluate_root_obligation(&obligation) } diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs index 98cb3f21555..9eceae8b44f 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -91,7 +91,12 @@ impl<'me, 'tcx> AscribeUserTypeCx<'me, 'tcx> { } fn prove_predicate(&self, predicate: Predicate<'tcx>, cause: ObligationCause<'tcx>) { - self.ocx.register_obligation(Obligation::new(cause, self.param_env, predicate)); + self.ocx.register_obligation(Obligation::new( + self.ocx.infcx.tcx, + cause, + self.param_env, + predicate, + )); } fn tcx(&self) -> TyCtxt<'tcx> { @@ -256,5 +261,5 @@ pub fn type_op_prove_predicate_with_cause<'tcx>( cause: ObligationCause<'tcx>, ) { let (param_env, ProvePredicate { predicate }) = key.into_parts(); - ocx.register_obligation(Obligation::new(cause, param_env, predicate)); + ocx.register_obligation(Obligation::new(ocx.infcx.tcx, cause, param_env, predicate)); } diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 006d813e5f9..f3cbfe27b3e 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -293,6 +293,15 @@ struct RcBox { value: T, } +/// Calculate layout for `RcBox` using the inner value's layout +fn rcbox_layout_for_value_layout(layout: Layout) -> Layout { + // Calculate layout using the given value layout. + // Previously, layout was calculated on the expression + // `&*(ptr as *const RcBox)`, but this created a misaligned + // reference (see #54908). + Layout::new::>().extend(layout).unwrap().0.pad_to_align() +} + /// A single-threaded reference-counting pointer. 'Rc' stands for 'Reference /// Counted'. /// @@ -1334,11 +1343,7 @@ impl Rc { allocate: impl FnOnce(Layout) -> Result, AllocError>, mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox, ) -> *mut RcBox { - // Calculate layout using the given value layout. - // Previously, layout was calculated on the expression - // `&*(ptr as *const RcBox)`, but this created a misaligned - // reference (see #54908). - let layout = Layout::new::>().extend(value_layout).unwrap().0.pad_to_align(); + let layout = rcbox_layout_for_value_layout(value_layout); unsafe { Rc::try_allocate_for_layout(value_layout, allocate, mem_to_rcbox) .unwrap_or_else(|_| handle_alloc_error(layout)) @@ -1357,11 +1362,7 @@ impl Rc { allocate: impl FnOnce(Layout) -> Result, AllocError>, mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox, ) -> Result<*mut RcBox, AllocError> { - // Calculate layout using the given value layout. - // Previously, layout was calculated on the expression - // `&*(ptr as *const RcBox)`, but this created a misaligned - // reference (see #54908). - let layout = Layout::new::>().extend(value_layout).unwrap().0.pad_to_align(); + let layout = rcbox_layout_for_value_layout(value_layout); // Allocate for the layout. let ptr = allocate(layout)?; @@ -1428,7 +1429,7 @@ impl Rc<[T]> { } } - /// Copy elements from slice into newly allocated Rc<\[T\]> + /// Copy elements from slice into newly allocated `Rc<[T]>` /// /// Unsafe because the caller must either take ownership or bind `T: Copy` #[cfg(not(no_global_oom_handling))] @@ -1440,6 +1441,48 @@ impl Rc<[T]> { } } + /// Create an `Rc<[T]>` by reusing the underlying memory + /// of a `Vec`. This will return the vector if the existing allocation + /// is not large enough. + #[cfg(not(no_global_oom_handling))] + fn try_from_vec_in_place(mut v: Vec) -> Result, Vec> { + let layout_elements = Layout::array::(v.len()).unwrap(); + let layout_allocation = Layout::array::(v.capacity()).unwrap(); + let layout_rcbox = rcbox_layout_for_value_layout(layout_elements); + let mut ptr = NonNull::new(v.as_mut_ptr()).expect("`Vec` stores `NonNull`"); + if layout_rcbox.size() > layout_allocation.size() + || layout_rcbox.align() > layout_allocation.align() + { + // Can't fit - calling `grow` would involve `realloc` + // (which copies the elements), followed by copying again. + return Err(v); + } + if layout_rcbox.size() < layout_allocation.size() + || layout_rcbox.align() < layout_allocation.align() + { + // We need to shrink the allocation so that it fits + // https://doc.rust-lang.org/nightly/std/alloc/trait.Allocator.html#memory-fitting + // SAFETY: + // - Vec allocates by requesting `Layout::array::(capacity)`, so this capacity matches + // - `layout_rcbox` is smaller + // If this fails, the ownership has not been transferred + if let Ok(p) = unsafe { Global.shrink(ptr.cast(), layout_allocation, layout_rcbox) } { + ptr = p.cast(); + } else { + return Err(v); + } + } + // Make sure the vec's memory isn't deallocated now + let v = mem::ManuallyDrop::new(v); + let ptr: *mut RcBox<[T]> = ptr::slice_from_raw_parts_mut(ptr.as_ptr(), v.len()) as _; + unsafe { + ptr::copy(ptr.cast::(), &mut (*ptr).value as *mut [T] as *mut T, v.len()); + ptr::write(&mut (*ptr).strong, Cell::new(1)); + ptr::write(&mut (*ptr).weak, Cell::new(1)); + Ok(Self::from_ptr(ptr)) + } + } + /// Constructs an `Rc<[T]>` from an iterator known to be of a certain size. /// /// Behavior is undefined should the size be wrong. @@ -1965,14 +2008,17 @@ impl From> for Rc<[T]> { /// assert_eq!(vec![1, 2, 3], *shared); /// ``` #[inline] - fn from(mut v: Vec) -> Rc<[T]> { - unsafe { - let rc = Rc::copy_from_slice(&v); - - // Allow the Vec to free its memory, but not destroy its contents - v.set_len(0); - - rc + fn from(v: Vec) -> Rc<[T]> { + match Rc::try_from_vec_in_place(v) { + Ok(rc) => rc, + Err(mut v) => { + unsafe { + let rc = Rc::copy_from_slice(&v); + // Allow the Vec to free its memory, but not destroy its contents + v.set_len(0); + rc + } + } } } } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 81cd7707488..37e07eb5998 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -333,6 +333,15 @@ struct ArcInner { data: T, } +/// Calculate layout for `ArcInner` using the inner value's layout +fn arcinner_layout_for_value_layout(layout: Layout) -> Layout { + // Calculate layout using the given value layout. + // Previously, layout was calculated on the expression + // `&*(ptr as *const ArcInner)`, but this created a misaligned + // reference (see #54908). + Layout::new::>().extend(layout).unwrap().0.pad_to_align() +} + unsafe impl Send for ArcInner {} unsafe impl Sync for ArcInner {} @@ -1154,11 +1163,7 @@ impl Arc { allocate: impl FnOnce(Layout) -> Result, AllocError>, mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, ) -> *mut ArcInner { - // Calculate layout using the given value layout. - // Previously, layout was calculated on the expression - // `&*(ptr as *const ArcInner)`, but this created a misaligned - // reference (see #54908). - let layout = Layout::new::>().extend(value_layout).unwrap().0.pad_to_align(); + let layout = arcinner_layout_for_value_layout(value_layout); unsafe { Arc::try_allocate_for_layout(value_layout, allocate, mem_to_arcinner) .unwrap_or_else(|_| handle_alloc_error(layout)) @@ -1176,11 +1181,7 @@ impl Arc { allocate: impl FnOnce(Layout) -> Result, AllocError>, mem_to_arcinner: impl FnOnce(*mut u8) -> *mut ArcInner, ) -> Result<*mut ArcInner, AllocError> { - // Calculate layout using the given value layout. - // Previously, layout was calculated on the expression - // `&*(ptr as *const ArcInner)`, but this created a misaligned - // reference (see #54908). - let layout = Layout::new::>().extend(value_layout).unwrap().0.pad_to_align(); + let layout = arcinner_layout_for_value_layout(value_layout); let ptr = allocate(layout)?; @@ -1246,7 +1247,7 @@ impl Arc<[T]> { } } - /// Copy elements from slice into newly allocated Arc<\[T\]> + /// Copy elements from slice into newly allocated `Arc<[T]>` /// /// Unsafe because the caller must either take ownership or bind `T: Copy`. #[cfg(not(no_global_oom_handling))] @@ -1260,6 +1261,49 @@ impl Arc<[T]> { } } + /// Create an `Arc<[T]>` by reusing the underlying memory + /// of a `Vec`. This will return the vector if the existing allocation + /// is not large enough. + #[cfg(not(no_global_oom_handling))] + fn try_from_vec_in_place(mut v: Vec) -> Result, Vec> { + let layout_elements = Layout::array::(v.len()).unwrap(); + let layout_allocation = Layout::array::(v.capacity()).unwrap(); + let layout_arcinner = arcinner_layout_for_value_layout(layout_elements); + let mut ptr = NonNull::new(v.as_mut_ptr()).expect("`Vec` stores `NonNull`"); + if layout_arcinner.size() > layout_allocation.size() + || layout_arcinner.align() > layout_allocation.align() + { + // Can't fit - calling `grow` would involve `realloc` + // (which copies the elements), followed by copying again. + return Err(v); + } + if layout_arcinner.size() < layout_allocation.size() + || layout_arcinner.align() < layout_allocation.align() + { + // We need to shrink the allocation so that it fits + // https://doc.rust-lang.org/nightly/std/alloc/trait.Allocator.html#memory-fitting + // SAFETY: + // - Vec allocates by requesting `Layout::array::(capacity)`, so this capacity matches + // - `layout_arcinner` is smaller + // If this fails, the ownership has not been transferred + if let Ok(p) = unsafe { Global.shrink(ptr.cast(), layout_allocation, layout_arcinner) } + { + ptr = p.cast(); + } else { + return Err(v); + } + } + // Make sure the vec's memory isn't deallocated now + let v = mem::ManuallyDrop::new(v); + let ptr: *mut ArcInner<[T]> = ptr::slice_from_raw_parts_mut(ptr.as_ptr(), v.len()) as _; + unsafe { + ptr::copy(ptr.cast::(), &mut (*ptr).data as *mut [T] as *mut T, v.len()); + ptr::write(&mut (*ptr).strong, atomic::AtomicUsize::new(1)); + ptr::write(&mut (*ptr).weak, atomic::AtomicUsize::new(1)); + Ok(Self::from_ptr(ptr)) + } + } + /// Constructs an `Arc<[T]>` from an iterator known to be of a certain size. /// /// Behavior is undefined should the size be wrong. @@ -2571,14 +2615,17 @@ impl From> for Arc<[T]> { /// assert_eq!(&[1, 2, 3], &shared[..]); /// ``` #[inline] - fn from(mut v: Vec) -> Arc<[T]> { - unsafe { - let arc = Arc::copy_from_slice(&v); - - // Allow the Vec to free its memory, but not destroy its contents - v.set_len(0); - - arc + fn from(v: Vec) -> Arc<[T]> { + match Arc::try_from_vec_in_place(v) { + Ok(rc) => rc, + Err(mut v) => { + unsafe { + let rc = Arc::copy_from_slice(&v); + // Allow the Vec to free its memory, but not destroy its contents + v.set_len(0); + rc + } + } } } } diff --git a/library/alloc/tests/arc.rs b/library/alloc/tests/arc.rs index ce40b5c9b0a..eb379e4d6a1 100644 --- a/library/alloc/tests/arc.rs +++ b/library/alloc/tests/arc.rs @@ -210,3 +210,18 @@ fn weak_may_dangle() { // `val` dropped here while still borrowed // borrow might be used here, when `val` is dropped and runs the `Drop` code for type `std::sync::Weak` } + +#[test] +fn arc_from_vec_opt() { + let mut v = Vec::with_capacity(64); + v.push(0usize); + let addr = v.as_ptr().cast::(); + let arc: Arc<[_]> = v.into(); + unsafe { + assert_eq!( + arc.as_ptr().cast::().offset_from(addr), + (std::mem::size_of::() * 2) as isize, + "Vector allocation not reused" + ); + } +} diff --git a/library/alloc/tests/rc.rs b/library/alloc/tests/rc.rs index efb39a60966..1d5f3c52006 100644 --- a/library/alloc/tests/rc.rs +++ b/library/alloc/tests/rc.rs @@ -206,3 +206,18 @@ fn weak_may_dangle() { // `val` dropped here while still borrowed // borrow might be used here, when `val` is dropped and runs the `Drop` code for type `std::rc::Weak` } + +#[test] +fn rc_from_vec_opt() { + let mut v = Vec::with_capacity(64); + v.push(0usize); + let addr = v.as_ptr().cast::(); + let rc: Rc<[_]> = v.into(); + unsafe { + assert_eq!( + rc.as_ptr().cast::().offset_from(addr), + (std::mem::size_of::() * 2) as isize, + "Vector allocation not reused" + ); + } +} diff --git a/library/core/src/future/mod.rs b/library/core/src/future/mod.rs index 6487aa08859..107cf92c1c0 100644 --- a/library/core/src/future/mod.rs +++ b/library/core/src/future/mod.rs @@ -82,6 +82,7 @@ where impl> Future for GenFuture { type Output = T::Return; + #[track_caller] fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { // SAFETY: Safe because we're !Unpin + !Drop, and this is just a field projection. let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) }; diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 34247c05845..c20ca69a1c6 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -338,6 +338,7 @@ pub macro debug_assert_matches($($arg:tt)*) { /// ``` #[macro_export] #[stable(feature = "matches_macro", since = "1.42.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "matches_macro")] macro_rules! matches { ($expression:expr, $(|)? $( $pattern:pat_param )|+ $( if $guard: expr )? $(,)?) => { match $expression { diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs index 7795bebaed5..65c882fb801 100644 --- a/src/bootstrap/cc_detect.rs +++ b/src/bootstrap/cc_detect.rs @@ -168,23 +168,7 @@ fn set_compiler( // compiler already takes into account the triple in question. t if t.contains("android") => { if let Some(ndk) = config.and_then(|c| c.ndk.as_ref()) { - let mut triple_iter = target.triple.split("-"); - let triple_translated = if let Some(arch) = triple_iter.next() { - let arch_new = match arch { - "arm" | "armv7" | "armv7neon" | "thumbv7" | "thumbv7neon" => "armv7a", - other => other, - }; - std::iter::once(arch_new).chain(triple_iter).collect::>().join("-") - } else { - target.triple.to_string() - }; - - // API 19 is the earliest API level supported by NDK r25b but AArch64 and x86_64 support - // begins at API level 21. - let api_level = - if t.contains("aarch64") || t.contains("x86_64") { "21" } else { "19" }; - let compiler = format!("{}{}-{}", triple_translated, api_level, compiler.clang()); - cfg.compiler(ndk.join("bin").join(compiler)); + cfg.compiler(ndk_compiler(compiler, &*target.triple, ndk)); } } @@ -236,8 +220,28 @@ fn set_compiler( } } +pub(crate) fn ndk_compiler(compiler: Language, triple: &str, ndk: &Path) -> PathBuf { + let mut triple_iter = triple.split("-"); + let triple_translated = if let Some(arch) = triple_iter.next() { + let arch_new = match arch { + "arm" | "armv7" | "armv7neon" | "thumbv7" | "thumbv7neon" => "armv7a", + other => other, + }; + std::iter::once(arch_new).chain(triple_iter).collect::>().join("-") + } else { + triple.to_string() + }; + + // API 19 is the earliest API level supported by NDK r25b but AArch64 and x86_64 support + // begins at API level 21. + let api_level = + if triple.contains("aarch64") || triple.contains("x86_64") { "21" } else { "19" }; + let compiler = format!("{}{}-{}", triple_translated, api_level, compiler.clang()); + ndk.join("bin").join(compiler) +} + /// The target programming language for a native compiler. -enum Language { +pub(crate) enum Language { /// The compiler is targeting C. C, /// The compiler is targeting C++. diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index af004aa5098..c61025b556a 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -15,6 +15,7 @@ use std::str::FromStr; use crate::builder::TaskPath; use crate::cache::{Interned, INTERNER}; +use crate::cc_detect::{ndk_compiler, Language}; use crate::channel::{self, GitInfo}; pub use crate::flags::Subcommand; use crate::flags::{Color, Flags}; @@ -1237,8 +1238,12 @@ impl Config { if let Some(s) = cfg.no_std { target.no_std = s; } - target.cc = cfg.cc.map(PathBuf::from); - target.cxx = cfg.cxx.map(PathBuf::from); + target.cc = cfg.cc.map(PathBuf::from).or_else(|| { + target.ndk.as_ref().map(|ndk| ndk_compiler(Language::C, &triple, ndk)) + }); + target.cxx = cfg.cxx.map(PathBuf::from).or_else(|| { + target.ndk.as_ref().map(|ndk| ndk_compiler(Language::CPlusPlus, &triple, ndk)) + }); target.ar = cfg.ar.map(PathBuf::from); target.ranlib = cfg.ranlib.map(PathBuf::from); target.linker = cfg.linker.map(PathBuf::from); diff --git a/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile b/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile index 69f88e49520..57e63cd39d2 100644 --- a/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile +++ b/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile @@ -9,7 +9,7 @@ RUN apt-get update -y && DEBIAN_FRONTEND=noninteractive apt-get install -y --no- curl \ file \ g++ \ - gcc-arm-linux-gnueabihf \ + g++-arm-linux-gnueabihf \ git \ libc6-dev \ libc6-dev-armhf-cross \ diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index d8063705582..cb0b8d4a9bc 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -76,6 +76,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { for predicate in predicates { debug!("testing predicate {:?}", predicate); let obligation = traits::Obligation::new( + infcx.tcx, traits::ObligationCause::dummy(), param_env, predicate, diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 8738986c7da..5ec2fe47e01 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -217,10 +217,7 @@ h1 a, .search-results a, .module-item .stab, .import-item .stab, -.result-name .primitive > i, .result-name .keyword > i, -.method .where, -.fn .where, -.where.fmt-newline { +.result-name .primitive > i, .result-name .keyword > i { color: var(--main-color); } @@ -1162,6 +1159,8 @@ pre.rust .doccomment { width: max-content; top: -2px; z-index: 1; + background-color: var(--tooltip-background-color); + color: var(--tooltip-color); } .example-wrap .tooltip::before { @@ -1170,10 +1169,10 @@ pre.rust .doccomment { top: 50%; left: 16px; margin-top: -5px; - border-width: 5px; - border-style: solid; display: none; z-index: 1; + border: 5px solid transparent; + border-right-color: var(--tooltip-background-color); } .example-wrap.ignore .tooltip::after { @@ -1393,12 +1392,6 @@ h3.variant { background-color: var(--button-background-color); border: 1px solid var(--border-color); border-radius: 2px; - color: var(--settings-button-color); -} - -#settings-menu > a:hover, #settings-menu > a:focus, -#help-button > a:hover, #help-button > a:focus { - border-color: var(--settings-button-border-focus); } #copy-path { diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 8052bd3fcb3..0e4dacb28f7 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -7,8 +7,6 @@ Original by Dempfi (https://github.com/dempfi/ayu) --main-background-color: #0f1419; --main-color: #c5c5c5; --settings-input-color: #ffb454; - --settings-button-color: #fff; - --settings-button-border-focus: #e0e0e0; --sidebar-background-color: #14191f; --sidebar-background-color-hover: rgba(70, 70, 70, 0.33); --code-block-background-color: #191f26; @@ -67,6 +65,8 @@ Original by Dempfi (https://github.com/dempfi/ayu) --test-arrow-hover-background-color: rgba(57, 175, 215, 0.368); --target-background-color: rgba(255, 236, 164, 0.06); --target-border-color: rgba(255, 180, 76, 0.85); + --tooltip-background-color: #314559; + --tooltip-color: #c5c5c5; --rust-logo-filter: drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) @@ -162,15 +162,6 @@ details.rustdoc-toggle > summary::before { color: #788797; } -.tooltip::after { - background-color: #314559; - color: #c5c5c5; -} - -.tooltip::before { - border-color: transparent #314559 transparent transparent; -} - #titles > button.selected { background-color: #141920 !important; border-bottom: 1px solid #ffb44c !important; @@ -208,10 +199,19 @@ kbd { box-shadow: inset 0 -1px 0 #5c6773; } +#settings-menu > a, #help-button > a { + color: #fff; +} + #settings-menu > a img { filter: invert(100); } +#settings-menu > a:hover, #settings-menu > a:focus, +#help-button > a:hover, #help-button > a:focus { + border-color: #e0e0e0; +} + .search-results .result-name span.alias { color: #c5c5c5; } diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 8680403f766..8e00591179f 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -2,8 +2,6 @@ --main-background-color: #353535; --main-color: #ddd; --settings-input-color: #2196f3; - --settings-button-color: #000; - --settings-button-border-focus: #ffb900; --sidebar-background-color: #505050; --sidebar-background-color-hover: #676767; --code-block-background-color: #2A2A2A; @@ -62,6 +60,8 @@ --test-arrow-hover-background-color: #4e8bca; --target-background-color: #494a3d; --target-border-color: #bb7410; + --tooltip-background-color: #000; + --tooltip-color: #fff; --rust-logo-filter: drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) @@ -84,16 +84,6 @@ details.rustdoc-toggle > summary::before { filter: invert(100%); } -.tooltip::after { - background-color: #000; - color: #fff; - border-color: #000; -} - -.tooltip::before { - border-color: transparent black transparent transparent; -} - #titles > button:not(.selected) { background-color: #252525; border-top-color: #252525; @@ -114,6 +104,15 @@ kbd { box-shadow: inset 0 -1px 0 #c6cbd1; } +#settings-menu > a, #help-button > a { + color: #000; +} + +#settings-menu > a:hover, #settings-menu > a:focus, +#help-button > a:hover, #help-button > a:focus { + border-color: #ffb900; +} + .search-results .result-name span.alias { color: #fff; } diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 37d5e8d1600..e23e3682b16 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -2,8 +2,6 @@ --main-background-color: white; --main-color: black; --settings-input-color: #2196f3; - --settings-button-color: #000; - --settings-button-border-focus: #717171; --sidebar-background-color: #F5F5F5; --sidebar-background-color-hover: #E0E0E0; --code-block-background-color: #F5F5F5; @@ -60,8 +58,10 @@ --test-arrow-background-color: rgba(78, 139, 202, 0.2); --test-arrow-hover-color: #f5f5f5; --test-arrow-hover-background-color: #4e8bca; - --target-background-color: #fdFfd3; + --target-background-color: #fdffd3; --target-border-color: #ad7c37; + --tooltip-background-color: #fdffd3; + --tooltip-color: #fff; --rust-logo-filter: initial; /* match border-color; uses https://codepen.io/sosuke/pen/Pjoqqp */ --crate-search-div-filter: invert(100%) sepia(0%) saturate(4223%) hue-rotate(289deg) @@ -77,15 +77,6 @@ body.source .example-wrap pre.rust a { background: #eee; } -.tooltip::after { - background-color: #000; - color: #fff; -} - -.tooltip::before { - border-color: transparent black transparent transparent; -} - #titles > button:not(.selected) { background-color: #e6e6e6; border-top-color: #e6e6e6; @@ -106,6 +97,15 @@ kbd { box-shadow: inset 0 -1px 0 #c6cbd1; } +#settings-menu > a, #help-button > a { + color: #000; +} + +#settings-menu > a:hover, #settings-menu > a:focus, +#help-button > a:hover, #help-button > a:focus { + border-color: #717171; +} + .search-results .result-name span.alias { color: #000; } diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js index 95cc265f1bd..5256ae916a7 100644 --- a/src/librustdoc/html/static/js/settings.js +++ b/src/librustdoc/html/static/js/settings.js @@ -9,13 +9,16 @@ const isSettingsPage = window.location.pathname.endsWith("/settings.html"); function changeSetting(settingName, value) { + if (settingName === "theme") { + const useSystem = value === "system preference" ? "true" : "false"; + updateLocalStorage("use-system-theme", useSystem); + } updateLocalStorage(settingName, value); switch (settingName) { case "theme": case "preferred-dark-theme": case "preferred-light-theme": - case "use-system-theme": updateSystemTheme(); updateLightAndDark(); break; @@ -45,7 +48,6 @@ } function showLightAndDark() { - addClass(document.getElementById("theme").parentElement, "hidden"); removeClass(document.getElementById("preferred-light-theme").parentElement, "hidden"); removeClass(document.getElementById("preferred-dark-theme").parentElement, "hidden"); } @@ -53,11 +55,11 @@ function hideLightAndDark() { addClass(document.getElementById("preferred-light-theme").parentElement, "hidden"); addClass(document.getElementById("preferred-dark-theme").parentElement, "hidden"); - removeClass(document.getElementById("theme").parentElement, "hidden"); } function updateLightAndDark() { - if (getSettingValue("use-system-theme") !== "false") { + const useSystem = getSettingValue("use-system-theme"); + if (useSystem === "true" || (useSystem === null && getSettingValue("theme") === null)) { showLightAndDark(); } else { hideLightAndDark(); @@ -91,7 +93,18 @@ }); onEachLazy(settingsElement.querySelectorAll("input[type=\"radio\"]"), elem => { const settingId = elem.name; - const settingValue = getSettingValue(settingId); + let settingValue = getSettingValue(settingId); + if (settingId === "theme") { + const useSystem = getSettingValue("use-system-theme"); + if (useSystem === "true" || settingValue === null) { + if (useSystem !== "false") { + settingValue = "system preference"; + } else { + // This is the default theme. + settingValue = "light"; + } + } + } if (settingValue !== null && settingValue !== "null") { elem.checked = settingValue === elem.value; } @@ -120,26 +133,30 @@ if (setting["options"] !== undefined) { // This is a select setting. - output += `

\ - ${setting_name}\ -
`; + output += `\ +
+ ${setting_name} +
`; onEach(setting["options"], option => { const checked = option === setting["default"] ? " checked" : ""; + const full = `${js_data_name}-${option.replace(/ /g,"-")}`; - output += ``; + output += `\ +`; }); output += "
"; } else { // This is a toggle. const checked = setting["default"] === true ? " checked" : ""; - output += ``; + output += `\ +`; } output += "
"; } @@ -156,16 +173,11 @@ theme_names.push("light", "dark", "ayu"); const settings = [ - { - "name": "Use system theme", - "js_name": "use-system-theme", - "default": true, - }, { "name": "Theme", "js_name": "theme", - "default": "light", - "options": theme_names, + "default": "system preference", + "options": theme_names.concat("system preference"), }, { "name": "Preferred light theme", diff --git a/src/test/run-make-fulldeps/tools.mk b/src/test/run-make-fulldeps/tools.mk index 33bf95ac165..0f5425daa16 100644 --- a/src/test/run-make-fulldeps/tools.mk +++ b/src/test/run-make-fulldeps/tools.mk @@ -40,6 +40,17 @@ endif # e.g. for `$(CC) -o $(RUN_BINFILE)`. RUN_BINFILE = $(TMPDIR)/$(1) +# Invoke the generated binary on the remote machine if compiletest was +# configured to use a remote test device, otherwise run it on the current host. +ifdef REMOTE_TEST_CLIENT +# FIXME: if a test requires additional files, this will need to be changed to +# also push them (by changing the 0 to the number of additional files, and +# providing the path of the additional files as the last arguments). +EXECUTE = $(REMOTE_TEST_CLIENT) run 0 $(RUN_BINFILE) +else +EXECUTE = $(RUN_BINFILE) +endif + # RUN and FAIL are basic way we will invoke the generated binary. On # non-windows platforms, they set the LD_LIBRARY_PATH environment # variable before running the binary. @@ -50,16 +61,16 @@ BIN = $(1) UNAME = $(shell uname) ifeq ($(UNAME),Darwin) -RUN = $(TARGET_RPATH_ENV) $(RUN_BINFILE) -FAIL = $(TARGET_RPATH_ENV) $(RUN_BINFILE) && exit 1 || exit 0 +RUN = $(TARGET_RPATH_ENV) $(EXECUTE) +FAIL = $(TARGET_RPATH_ENV) $(EXECUTE) && exit 1 || exit 0 DYLIB_GLOB = lib$(1)*.dylib DYLIB = $(TMPDIR)/lib$(1).dylib STATICLIB = $(TMPDIR)/lib$(1).a STATICLIB_GLOB = lib$(1)*.a else ifdef IS_WINDOWS -RUN = PATH="$(PATH):$(TARGET_RPATH_DIR)" $(RUN_BINFILE) -FAIL = PATH="$(PATH):$(TARGET_RPATH_DIR)" $(RUN_BINFILE) && exit 1 || exit 0 +RUN = PATH="$(PATH):$(TARGET_RPATH_DIR)" $(EXECUTE) +FAIL = PATH="$(PATH):$(TARGET_RPATH_DIR)" $(EXECUTE) && exit 1 || exit 0 DYLIB_GLOB = $(1)*.dll DYLIB = $(TMPDIR)/$(1).dll ifdef IS_MSVC @@ -73,8 +84,8 @@ endif BIN = $(1).exe LLVM_FILECHECK := $(shell cygpath -u "$(LLVM_FILECHECK)") else -RUN = $(TARGET_RPATH_ENV) $(RUN_BINFILE) -FAIL = $(TARGET_RPATH_ENV) $(RUN_BINFILE) && exit 1 || exit 0 +RUN = $(TARGET_RPATH_ENV) $(EXECUTE) +FAIL = $(TARGET_RPATH_ENV) $(EXECUTE) && exit 1 || exit 0 DYLIB_GLOB = lib$(1)*.so DYLIB = $(TMPDIR)/lib$(1).so STATICLIB = $(TMPDIR)/lib$(1).a diff --git a/src/test/run-make/issue-36710/Makefile b/src/test/run-make/issue-36710/Makefile index 986a3f4e64b..d6145c07126 100644 --- a/src/test/run-make/issue-36710/Makefile +++ b/src/test/run-make/issue-36710/Makefile @@ -1,6 +1,7 @@ -# ignore-cross-compile $(call RUN,foo) expects to run the target executable natively -# so it won't work with remote-test-server # ignore-none no-std is not supported +# ignore-wasm32 FIXME: don't attempt to compile C++ to WASM +# ignore-wasm64 FIXME: don't attempt to compile C++ to WASM +# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std` # ignore-musl FIXME: this makefile needs teaching how to use a musl toolchain # (see dist-i586-gnu-i586-i686-musl Dockerfile) diff --git a/src/test/rustdoc-gui/codeblock-tooltip.goml b/src/test/rustdoc-gui/codeblock-tooltip.goml index 8e681a2a0c3..caa1ab8f31e 100644 --- a/src/test/rustdoc-gui/codeblock-tooltip.goml +++ b/src/test/rustdoc-gui/codeblock-tooltip.goml @@ -4,7 +4,7 @@ show-text: true define-function: ( "check-colors", - (theme), + (theme, background, color, border), [ // Setting the theme. ("local-storage", {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}), @@ -30,6 +30,25 @@ define-function: ( ".docblock .example-wrap.compile_fail", {"border-left": "2px solid rgb(255, 0, 0)"}, )), + ("assert-css", ( + ".docblock .example-wrap.compile_fail .tooltip::after", + { + "content": '"This example deliberately fails to compile"', + "text-align": "center", + "padding": "5px 3px 3px", + "background-color": |background|, + "color": |color|, + "border": "1px solid " + |border|, + }, + )), + ("assert-css", ( + ".docblock .example-wrap.compile_fail .tooltip::before", + { + "border-width": "5px", + "border-style": "solid", + "border-color": "rgba(0, 0, 0, 0) " + |background| + " rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)", + }, + )), // should_panic block ("assert-css", ( @@ -51,6 +70,25 @@ define-function: ( ".docblock .example-wrap.should_panic", {"border-left": "2px solid rgb(255, 0, 0)"}, )), + ("assert-css", ( + ".docblock .example-wrap.should_panic .tooltip::after", + { + "content": '"This example panics"', + "text-align": "center", + "padding": "5px 3px 3px", + "background-color": |background|, + "color": |color|, + "border": "1px solid " + |border|, + }, + )), + ("assert-css", ( + ".docblock .example-wrap.should_panic .tooltip::before", + { + "border-width": "5px", + "border-style": "solid", + "border-color": "rgba(0, 0, 0, 0) " + |background| + " rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)", + }, + )), // ignore block ("assert-css", ( @@ -72,9 +110,43 @@ define-function: ( ".docblock .example-wrap.ignore", {"border-left": "2px solid rgb(255, 142, 0)"}, )), + ("assert-css", ( + ".docblock .example-wrap.ignore .tooltip::after", + { + "content": '"This example is not tested"', + "text-align": "center", + "padding": "5px 3px 3px", + "background-color": |background|, + "color": |color|, + "border": "1px solid " + |border|, + }, + )), + ("assert-css", ( + ".docblock .example-wrap.ignore .tooltip::before", + { + "border-width": "5px", + "border-style": "solid", + "border-color": "rgba(0, 0, 0, 0) " + |background| + " rgba(0, 0, 0, 0) rgba(0, 0, 0, 0)", + }, + )), ], ) -call-function: ("check-colors", ("ayu")) -call-function: ("check-colors", ("dark")) -call-function: ("check-colors", ("light")) +call-function: ("check-colors", { + "theme": "ayu", + "background": "rgb(49, 69, 89)", + "color": "rgb(197, 197, 197)", + "border": "rgb(92, 103, 115)", +}) +call-function: ("check-colors", { + "theme": "dark", + "background": "rgb(0, 0, 0)", + "color": "rgb(255, 255, 255)", + "border": "rgb(224, 224, 224)", +}) +call-function: ("check-colors", { + "theme": "light", + "background": "rgb(253, 255, 211)", + "color": "rgb(255, 255, 255)", + "border": "rgb(224, 224, 224)", +}) diff --git a/src/test/rustdoc-gui/settings.goml b/src/test/rustdoc-gui/settings.goml index 7e7971d47fb..fc3beaa53fa 100644 --- a/src/test/rustdoc-gui/settings.goml +++ b/src/test/rustdoc-gui/settings.goml @@ -37,8 +37,7 @@ click: "#settings-menu" wait-for: "#settings" // We check that the "Use system theme" is disabled. -assert-property: ("#use-system-theme", {"checked": "false"}) -assert: "//*[@class='setting-line']//span[text()='Use system theme']" +assert-property: ("#theme-system-preference", {"checked": "false"}) // Meaning that only the "theme" menu is showing up. assert: ".setting-line:not(.hidden) #theme" assert: ".setting-line.hidden #preferred-dark-theme" @@ -115,13 +114,6 @@ assert-css: ( "border-color": "rgb(221, 221, 221)", }, ) -assert-css: ( - "#use-system-theme", - { - "background-color": "rgba(0, 0, 0, 0)", - "border-color": "rgb(221, 221, 221)", - } -) // Let's start with the hover for toggles. move-cursor-to: "#auto-hide-large-items" assert-css: ( @@ -131,14 +123,6 @@ assert-css: ( "border-color": "rgb(33, 150, 243)", }, ) -move-cursor-to: "#use-system-theme" -assert-css: ( - "#use-system-theme", - { - "background-color": "rgba(0, 0, 0, 0)", - "border-color": "rgb(33, 150, 243)", - } -) move-cursor-to: "#settings-menu > a" // Let's now check with the focus for toggles. focus: "#auto-hide-large-items" @@ -150,15 +134,6 @@ assert-css: ( "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", }, ) -focus: "#use-system-theme" -assert-css: ( - "#use-system-theme", - { - "background-color": "rgba(0, 0, 0, 0)", - "border-color": "rgb(221, 221, 221)", - "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", - }, -) // Now we check we both focus and hover for toggles. move-cursor-to: "#auto-hide-large-items" focus: "#auto-hide-large-items" @@ -170,24 +145,12 @@ assert-css: ( "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", }, ) -move-cursor-to: "#use-system-theme" -focus: "#use-system-theme" -assert-css: ( - "#use-system-theme", - { - "background-color": "rgba(0, 0, 0, 0)", - "border-color": "rgb(33, 150, 243)", - "box-shadow": "rgb(33, 150, 243) 0px 0px 1px 1px", - }, -) // We now switch the display. -click: "#use-system-theme" +click: "#theme-system-preference" // Wait for the hidden element to show up. wait-for: ".setting-line:not(.hidden) #preferred-dark-theme" assert: ".setting-line:not(.hidden) #preferred-light-theme" -// Check that the theme picking is hidden. -assert: ".setting-line.hidden #theme" // We check their text as well. assert-text: ("#preferred-dark-theme .setting-name", "Preferred dark theme") diff --git a/src/test/rustdoc-gui/theme-change.goml b/src/test/rustdoc-gui/theme-change.goml index b1de3c36614..cc47f1f450c 100644 --- a/src/test/rustdoc-gui/theme-change.goml +++ b/src/test/rustdoc-gui/theme-change.goml @@ -2,31 +2,66 @@ goto: "file://" + |DOC_PATH| + "/test_docs/index.html" local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "dark"} reload: + +store-value: (background_light, "rgb(255, 255, 255)") +store-value: (background_dark, "rgb(53, 53, 53)") +store-value: (background_ayu, "rgb(15, 20, 25)") + click: "#settings-menu" wait-for: "#theme-ayu" click: "#theme-ayu" // should be the ayu theme so let's check the color. -wait-for-css: ("body", { "background-color": "rgb(15, 20, 25)" }) +wait-for-css: ("body", { "background-color": |background_ayu| }) assert-local-storage: { "rustdoc-theme": "ayu" } click: "#theme-light" // should be the light theme so let's check the color. -wait-for-css: ("body", { "background-color": "rgb(255, 255, 255)" }) +wait-for-css: ("body", { "background-color": |background_light| }) assert-local-storage: { "rustdoc-theme": "light" } click: "#theme-dark" // Should be the dark theme so let's check the color. -wait-for-css: ("body", { "background-color": "rgb(53, 53, 53)" }) +wait-for-css: ("body", { "background-color": |background_dark| }) assert-local-storage: { "rustdoc-theme": "dark" } +local-storage: { + "rustdoc-preferred-light-theme": "light", + "rustdoc-preferred-dark-theme": "light", +} goto: "file://" + |DOC_PATH| + "/settings.html" + wait-for: "#settings" click: "#theme-light" -wait-for-css: ("body", { "background-color": "rgb(255, 255, 255)" }) +wait-for-css: ("body", { "background-color": |background_light| }) assert-local-storage: { "rustdoc-theme": "light" } click: "#theme-dark" -wait-for-css: ("body", { "background-color": "rgb(53, 53, 53)" }) +wait-for-css: ("body", { "background-color": |background_dark| }) assert-local-storage: { "rustdoc-theme": "dark" } click: "#theme-ayu" -wait-for-css: ("body", { "background-color": "rgb(15, 20, 25)" }) +wait-for-css: ("body", { "background-color": |background_ayu| }) assert-local-storage: { "rustdoc-theme": "ayu" } + +assert-local-storage-false: { "rustdoc-use-system-theme": "true" } +click: "#theme-system-preference" +wait-for: ".setting-line:not(.hidden) #preferred-light-theme" +assert-local-storage: { "rustdoc-use-system-theme": "true" } +// We click on both preferred light and dark themes to be sure that there is a change. +click: "#preferred-light-theme-dark" +click: "#preferred-dark-theme-dark" +wait-for-css: ("body", { "background-color": |background_dark| }) + +reload: +// Ensure that the "preferred themes" are still displayed. +wait-for: ".setting-line:not(.hidden) #preferred-light-theme" +click: "#theme-light" +wait-for-css: ("body", { "background-color": |background_light| }) +assert-local-storage: { "rustdoc-theme": "light" } +// Ensure it's now hidden again +wait-for: ".setting-line.hidden #preferred-light-theme" +// And ensure the theme was rightly set. +wait-for-css: ("body", { "background-color": |background_light| }) +assert-local-storage: { "rustdoc-theme": "light" } + +reload: +wait-for: "#settings" +assert: ".setting-line.hidden #preferred-light-theme" diff --git a/src/test/ui/async-await/in-trait/early-bound-1.rs b/src/test/ui/async-await/in-trait/early-bound-1.rs new file mode 100644 index 00000000000..6b3b142014b --- /dev/null +++ b/src/test/ui/async-await/in-trait/early-bound-1.rs @@ -0,0 +1,17 @@ +// check-pass +// edition:2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +pub trait Foo { + async fn foo(&mut self); +} + +struct MyFoo<'a>(&'a mut ()); + +impl<'a> Foo for MyFoo<'a> { + async fn foo(&mut self) {} +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/early-bound-2.rs b/src/test/ui/async-await/in-trait/early-bound-2.rs new file mode 100644 index 00000000000..270443229b0 --- /dev/null +++ b/src/test/ui/async-await/in-trait/early-bound-2.rs @@ -0,0 +1,15 @@ +// check-pass +// edition:2021 + +#![feature(async_fn_in_trait)] +#![allow(incomplete_features)] + +pub trait Foo { + async fn foo(&mut self); +} + +impl Foo for &mut T { + async fn foo(&mut self) {} +} + +fn main() {} diff --git a/src/test/ui/async-await/in-trait/object-safety.rs b/src/test/ui/async-await/in-trait/object-safety.rs new file mode 100644 index 00000000000..a8bc35f7e0c --- /dev/null +++ b/src/test/ui/async-await/in-trait/object-safety.rs @@ -0,0 +1,13 @@ +// edition:2021 + +#![feature(async_fn_in_trait)] +//~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes + +trait Foo { + async fn foo(&self); +} + +fn main() { + let x: &dyn Foo = todo!(); + //~^ ERROR the trait `Foo` cannot be made into an object +} diff --git a/src/test/ui/async-await/in-trait/object-safety.stderr b/src/test/ui/async-await/in-trait/object-safety.stderr new file mode 100644 index 00000000000..0b318f71f39 --- /dev/null +++ b/src/test/ui/async-await/in-trait/object-safety.stderr @@ -0,0 +1,27 @@ +warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/object-safety.rs:3:12 + | +LL | #![feature(async_fn_in_trait)] + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #91611 for more information + = note: `#[warn(incomplete_features)]` on by default + +error[E0038]: the trait `Foo` cannot be made into an object + --> $DIR/object-safety.rs:11:12 + | +LL | let x: &dyn Foo = todo!(); + | ^^^^^^^^ `Foo` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $DIR/object-safety.rs:7:14 + | +LL | trait Foo { + | --- this trait cannot be made into an object... +LL | async fn foo(&self); + | ^^^ ...because method `foo` is `async` + = help: consider moving `foo` to another trait + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0038`. diff --git a/src/test/ui/async-await/track-caller/panic-track-caller.rs b/src/test/ui/async-await/track-caller/panic-track-caller.rs new file mode 100644 index 00000000000..b113c56412f --- /dev/null +++ b/src/test/ui/async-await/track-caller/panic-track-caller.rs @@ -0,0 +1,76 @@ +// run-pass +// edition:2021 +// needs-unwind +#![feature(closure_track_caller)] + +use std::future::Future; +use std::panic; +use std::sync::{Arc, Mutex}; +use std::task::{Context, Poll, Wake}; +use std::thread::{self, Thread}; + +/// A waker that wakes up the current thread when called. +struct ThreadWaker(Thread); + +impl Wake for ThreadWaker { + fn wake(self: Arc) { + self.0.unpark(); + } +} + +/// Run a future to completion on the current thread. +fn block_on(fut: impl Future) -> T { + // Pin the future so it can be polled. + let mut fut = Box::pin(fut); + + // Create a new context to be passed to the future. + let t = thread::current(); + let waker = Arc::new(ThreadWaker(t)).into(); + let mut cx = Context::from_waker(&waker); + + // Run the future to completion. + loop { + match fut.as_mut().poll(&mut cx) { + Poll::Ready(res) => return res, + Poll::Pending => thread::park(), + } + } +} + +async fn bar() { + panic!() +} + +async fn foo() { + bar().await +} + +#[track_caller] +async fn bar_track_caller() { + panic!() +} + +async fn foo_track_caller() { + bar_track_caller().await +} + +fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 { + let loc = Arc::new(Mutex::new(None)); + + let hook = panic::take_hook(); + { + let loc = loc.clone(); + panic::set_hook(Box::new(move |info| { + *loc.lock().unwrap() = info.location().map(|loc| loc.line()) + })); + } + panic::catch_unwind(f).unwrap_err(); + panic::set_hook(hook); + let x = loc.lock().unwrap().unwrap(); + x +} + +fn main() { + assert_eq!(panicked_at(|| block_on(foo())), 41); + assert_eq!(panicked_at(|| block_on(foo_track_caller())), 54); +} diff --git a/src/test/ui/consts/const-eval/issue-104390.rs b/src/test/ui/consts/const-eval/issue-104390.rs new file mode 100644 index 00000000000..602d818245a --- /dev/null +++ b/src/test/ui/consts/const-eval/issue-104390.rs @@ -0,0 +1,10 @@ +fn f1() -> impl Sized { & 2E } //~ ERROR expected at least one digit in exponent +fn f2() -> impl Sized { && 2E } //~ ERROR expected at least one digit in exponent +fn f3() -> impl Sized { &'a 2E } //~ ERROR expected at least one digit in exponent +//~^ ERROR borrow expressions cannot be annotated with lifetimes +fn f4() -> impl Sized { &'static 2E } //~ ERROR expected at least one digit in exponent +//~^ ERROR borrow expressions cannot be annotated with lifetimes +fn f5() -> impl Sized { *& 2E } //~ ERROR expected at least one digit in exponent +fn f6() -> impl Sized { &'_ 2E } //~ ERROR expected at least one digit in exponent +//~^ ERROR borrow expressions cannot be annotated with lifetimes +fn main() {} diff --git a/src/test/ui/consts/const-eval/issue-104390.stderr b/src/test/ui/consts/const-eval/issue-104390.stderr new file mode 100644 index 00000000000..865b9996ea3 --- /dev/null +++ b/src/test/ui/consts/const-eval/issue-104390.stderr @@ -0,0 +1,65 @@ +error: expected at least one digit in exponent + --> $DIR/issue-104390.rs:1:27 + | +LL | fn f1() -> impl Sized { & 2E } + | ^^ + +error: expected at least one digit in exponent + --> $DIR/issue-104390.rs:2:28 + | +LL | fn f2() -> impl Sized { && 2E } + | ^^ + +error: expected at least one digit in exponent + --> $DIR/issue-104390.rs:3:29 + | +LL | fn f3() -> impl Sized { &'a 2E } + | ^^ + +error: expected at least one digit in exponent + --> $DIR/issue-104390.rs:5:34 + | +LL | fn f4() -> impl Sized { &'static 2E } + | ^^ + +error: expected at least one digit in exponent + --> $DIR/issue-104390.rs:7:28 + | +LL | fn f5() -> impl Sized { *& 2E } + | ^^ + +error: expected at least one digit in exponent + --> $DIR/issue-104390.rs:8:29 + | +LL | fn f6() -> impl Sized { &'_ 2E } + | ^^ + +error: borrow expressions cannot be annotated with lifetimes + --> $DIR/issue-104390.rs:3:25 + | +LL | fn f3() -> impl Sized { &'a 2E } + | ^--^^^ + | | + | annotated with lifetime here + | help: remove the lifetime annotation + +error: borrow expressions cannot be annotated with lifetimes + --> $DIR/issue-104390.rs:5:25 + | +LL | fn f4() -> impl Sized { &'static 2E } + | ^-------^^^ + | | + | annotated with lifetime here + | help: remove the lifetime annotation + +error: borrow expressions cannot be annotated with lifetimes + --> $DIR/issue-104390.rs:8:25 + | +LL | fn f6() -> impl Sized { &'_ 2E } + | ^--^^^ + | | + | annotated with lifetime here + | help: remove the lifetime annotation + +error: aborting due to 9 previous errors + diff --git a/src/test/ui/dyn-star/return.rs b/src/test/ui/dyn-star/return.rs new file mode 100644 index 00000000000..fa3d8d7d506 --- /dev/null +++ b/src/test/ui/dyn-star/return.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(dyn_star)] +//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + +fn _foo() -> dyn* Unpin { + 4usize +} + +fn main() {} diff --git a/src/test/ui/dyn-star/return.stderr b/src/test/ui/dyn-star/return.stderr new file mode 100644 index 00000000000..e000351a68f --- /dev/null +++ b/src/test/ui/dyn-star/return.stderr @@ -0,0 +1,11 @@ +warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/return.rs:3:12 + | +LL | #![feature(dyn_star)] + | ^^^^^^^^ + | + = note: see issue #91611 for more information + = note: `#[warn(incomplete_features)]` on by default + +warning: 1 warning emitted + diff --git a/src/test/ui/impl-trait/in-trait/object-safety.stderr b/src/test/ui/impl-trait/in-trait/object-safety.stderr index 9a1554b5e1c..ca0e760ff6d 100644 --- a/src/test/ui/impl-trait/in-trait/object-safety.stderr +++ b/src/test/ui/impl-trait/in-trait/object-safety.stderr @@ -5,12 +5,12 @@ LL | let i = Box::new(42_u32) as Box; | ^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety.rs:7:8 + --> $DIR/object-safety.rs:7:22 | LL | trait Foo { | --- this trait cannot be made into an object... LL | fn baz(&self) -> impl Debug; - | ^^^ ...because method `baz` references an `impl Trait` type in its return type + | ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type = help: consider moving `baz` to another trait error[E0038]: the trait `Foo` cannot be made into an object @@ -20,12 +20,12 @@ LL | let s = i.baz(); | ^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety.rs:7:8 + --> $DIR/object-safety.rs:7:22 | LL | trait Foo { | --- this trait cannot be made into an object... LL | fn baz(&self) -> impl Debug; - | ^^^ ...because method `baz` references an `impl Trait` type in its return type + | ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type = help: consider moving `baz` to another trait error[E0038]: the trait `Foo` cannot be made into an object @@ -35,12 +35,12 @@ LL | let i = Box::new(42_u32) as Box; | ^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety.rs:7:8 + --> $DIR/object-safety.rs:7:22 | LL | trait Foo { | --- this trait cannot be made into an object... LL | fn baz(&self) -> impl Debug; - | ^^^ ...because method `baz` references an `impl Trait` type in its return type + | ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type = help: consider moving `baz` to another trait = note: required for `Box` to implement `CoerceUnsized>` = note: required by cast to type `Box` diff --git a/src/test/ui/lint/issue-104392.rs b/src/test/ui/lint/issue-104392.rs new file mode 100644 index 00000000000..d5608edb46f --- /dev/null +++ b/src/test/ui/lint/issue-104392.rs @@ -0,0 +1,11 @@ +fn main() { + { unsafe 92 } //~ ERROR expected `{`, found `92` +} + +fn foo() { + { mod 92 } //~ ERROR expected identifier, found `92` +} + +fn bar() { + { trait 92 } //~ ERROR expected identifier, found `92` +} diff --git a/src/test/ui/lint/issue-104392.stderr b/src/test/ui/lint/issue-104392.stderr new file mode 100644 index 00000000000..8e466439ae6 --- /dev/null +++ b/src/test/ui/lint/issue-104392.stderr @@ -0,0 +1,27 @@ +error: expected `{`, found `92` + --> $DIR/issue-104392.rs:2:14 + | +LL | { unsafe 92 } + | ------ ^^ expected `{` + | | + | while parsing this `unsafe` expression + | +help: try placing this code inside a block + | +LL | { unsafe { 92 } } + | + + + +error: expected identifier, found `92` + --> $DIR/issue-104392.rs:6:11 + | +LL | { mod 92 } + | ^^ expected identifier + +error: expected identifier, found `92` + --> $DIR/issue-104392.rs:10:13 + | +LL | { trait 92 } + | ^^ expected identifier + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/typeck/issue-103899.rs b/src/test/ui/typeck/issue-103899.rs index 9d5341dab42..ac9e4c71696 100644 --- a/src/test/ui/typeck/issue-103899.rs +++ b/src/test/ui/typeck/issue-103899.rs @@ -1,9 +1,6 @@ // check-fail // failure-status: 101 -// normalize-stderr-test "note: .*" -> "" -// normalize-stderr-test "thread 'rustc' .*" -> "" -// normalize-stderr-test " .*\n" -> "" -// normalize-stderr-test " .*\n" -> "" +// dont-check-compiler-stderr // known-bug: #103899 trait BaseWithAssoc { diff --git a/src/test/ui/typeck/issue-103899.stderr b/src/test/ui/typeck/issue-103899.stderr deleted file mode 100644 index 836c6ee486f..00000000000 --- a/src/test/ui/typeck/issue-103899.stderr +++ /dev/null @@ -1,12 +0,0 @@ - -stack -error: - - - - - - - - -query#0#1end \ No newline at end of file diff --git a/src/test/ui/typeck/issue-104510-ice.rs b/src/test/ui/typeck/issue-104510-ice.rs new file mode 100644 index 00000000000..157bdf07e38 --- /dev/null +++ b/src/test/ui/typeck/issue-104510-ice.rs @@ -0,0 +1,16 @@ +// needs-asm-support +// only-x86_64 + +struct W(Oops); +//~^ ERROR cannot find type `Oops` in this scope + +unsafe fn test() { + let j = W(()); + let pointer = &j as *const _; + core::arch::asm!( + "nop", + in("eax") pointer, + ); +} + +fn main() {} diff --git a/src/test/ui/typeck/issue-104510-ice.stderr b/src/test/ui/typeck/issue-104510-ice.stderr new file mode 100644 index 00000000000..ddb510ef047 --- /dev/null +++ b/src/test/ui/typeck/issue-104510-ice.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `Oops` in this scope + --> $DIR/issue-104510-ice.rs:4:21 + | +LL | struct W(Oops); + | ^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index a37ee82d4c8..218dbeaddca 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -1156,7 +1156,7 @@ fn needless_borrow_impl_arg_position<'tcx>( } let predicate = EarlyBinder(predicate).subst(cx.tcx, &substs_with_referent_ty); - let obligation = Obligation::new(ObligationCause::dummy(), cx.param_env, predicate); + let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate); let infcx = cx.tcx.infer_ctxt().build(); infcx.predicate_must_hold_modulo_regions(&obligation) }) diff --git a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs index 090f9f8ff73..5c6a342b3d0 100644 --- a/src/tools/clippy/clippy_lints/src/manual_async_fn.rs +++ b/src/tools/clippy/clippy_lints/src/manual_async_fn.rs @@ -6,7 +6,7 @@ use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{ AsyncGeneratorKind, Block, Body, Closure, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericArg, GenericBound, - HirId, IsAsync, ItemKind, LifetimeName, Term, TraitRef, Ty, TyKind, TypeBindingKind, + HirId, ItemKind, LifetimeName, Term, TraitRef, Ty, TyKind, TypeBindingKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualAsyncFn { ) { if_chain! { if let Some(header) = kind.header(); - if header.asyncness == IsAsync::NotAsync; + if !header.asyncness.is_async(); // Check that this function returns `impl Future` if let FnRetTy::Return(ret_ty) = decl.output; if let Some((trait_ref, output_lifetimes)) = future_trait_ref(cx, ret_ty); diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 642a64ae77b..c7775313ecd 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -419,7 +419,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< if trait_predicates.any(|predicate| { let predicate = EarlyBinder(predicate).subst(cx.tcx, new_subst); - let obligation = Obligation::new(ObligationCause::dummy(), cx.param_env, predicate); + let obligation = Obligation::new(cx.tcx, ObligationCause::dummy(), cx.param_env, predicate); !cx.tcx.infer_ctxt().build().predicate_must_hold_modulo_regions(&obligation) }) { return false; diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index 0d74c90a834..c8c6f32c6c9 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -695,6 +695,7 @@ fn matches_preds<'tcx>( .type_implements_trait(p.def_id, ty, p.substs, cx.param_env) .must_apply_modulo_regions(), ExistentialPredicate::Projection(p) => infcx.predicate_must_hold_modulo_regions(&Obligation::new( + cx.tcx, ObligationCause::dummy(), cx.param_env, cx.tcx.mk_predicate(Binder::bind_with_vars( diff --git a/src/tools/clippy/clippy_lints/src/unused_async.rs b/src/tools/clippy/clippy_lints/src/unused_async.rs index bf487c7ca20..3538bef6e06 100644 --- a/src/tools/clippy/clippy_lints/src/unused_async.rs +++ b/src/tools/clippy/clippy_lints/src/unused_async.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_help; use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, Visitor}; -use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, IsAsync, YieldSource}; +use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, YieldSource}; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::hir::nested_filter; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -68,7 +68,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAsync { span: Span, hir_id: HirId, ) { - if !span.from_expansion() && fn_kind.asyncness() == IsAsync::Async { + if !span.from_expansion() && fn_kind.asyncness().is_async() { let mut visitor = AsyncFnVisitor { cx, found_await: false }; walk_fn(&mut visitor, fn_kind, fn_decl, body.id(), hir_id); if !visitor.found_await { diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index d32cf1a7936..bb91317d67f 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -87,10 +87,10 @@ use rustc_hir::hir_id::{HirIdMap, HirIdSet}; use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk}; use rustc_hir::{ - def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Constness, Destination, Expr, - ExprKind, FnDecl, HirId, Impl, ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, MatchSource, - Mutability, Node, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, - TraitRef, TyKind, UnOp, + def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Closure, Constness, + Destination, Expr, ExprKind, FnDecl, HirId, Impl, ImplItem, ImplItemKind, Item, ItemKind, + LangItem, Local, MatchSource, Mutability, Node, Param, Pat, PatKind, Path, PathSegment, PrimTy, + QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind, UnOp, }; use rustc_lexer::{tokenize, TokenKind}; use rustc_lint::{LateContext, Level, Lint, LintContext}; @@ -1861,7 +1861,7 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>, /// Checks if the given function kind is an async function. pub fn is_async_fn(kind: FnKind<'_>) -> bool { - matches!(kind, FnKind::ItemFn(_, _, header) if header.asyncness == IsAsync::Async) + matches!(kind, FnKind::ItemFn(_, _, header) if header.asyncness.is_async()) } /// Peels away all the compiler generated code surrounding the body of an async function, diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 8d8ca101cd0..ebce0283fba 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2987,6 +2987,10 @@ impl<'test> TestCx<'test> { cmd.env("LLVM_BIN_DIR", llvm_bin_dir); } + if let Some(ref remote_test_client) = self.config.remote_test_client { + cmd.env("REMOTE_TEST_CLIENT", remote_test_client); + } + // We don't want RUSTFLAGS set from the outside to interfere with // compiler flags set in the test cases: cmd.env_remove("RUSTFLAGS"); diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index b8398377585..d3e139e4651 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -9340e5c1b9dee53fd32a18f7bfb54faabfe00b7b +2f8d8040166a730d0da7bba0f2864f0ef7ff6364 diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index 617f90dfaa5..bc0b71fbc20 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -22,21 +22,44 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); - this.assert_target_os("linux", "clock_gettime"); + this.assert_target_os_is_unix("clock_gettime"); let clk_id = this.read_scalar(clk_id_op)?.to_i32()?; - // Linux has two main kinds of clocks. REALTIME clocks return the actual time since the - // Unix epoch, including effects which may cause time to move backwards such as NTP. - // Linux further distinguishes regular and "coarse" clocks, but the "coarse" version - // is just specified to be "faster and less precise", so we implement both the same way. - let absolute_clocks = - [this.eval_libc_i32("CLOCK_REALTIME")?, this.eval_libc_i32("CLOCK_REALTIME_COARSE")?]; - // The second kind is MONOTONIC clocks for which 0 is an arbitrary time point, but they are - // never allowed to go backwards. We don't need to do any additonal monotonicity - // enforcement because std::time::Instant already guarantees that it is monotonic. - let relative_clocks = - [this.eval_libc_i32("CLOCK_MONOTONIC")?, this.eval_libc_i32("CLOCK_MONOTONIC_COARSE")?]; + let absolute_clocks; + let mut relative_clocks; + + match this.tcx.sess.target.os.as_ref() { + "linux" => { + // Linux has two main kinds of clocks. REALTIME clocks return the actual time since the + // Unix epoch, including effects which may cause time to move backwards such as NTP. + // Linux further distinguishes regular and "coarse" clocks, but the "coarse" version + // is just specified to be "faster and less precise", so we implement both the same way. + absolute_clocks = vec![ + this.eval_libc_i32("CLOCK_REALTIME")?, + this.eval_libc_i32("CLOCK_REALTIME_COARSE")?, + ]; + // The second kind is MONOTONIC clocks for which 0 is an arbitrary time point, but they are + // never allowed to go backwards. We don't need to do any additonal monotonicity + // enforcement because std::time::Instant already guarantees that it is monotonic. + relative_clocks = vec![ + this.eval_libc_i32("CLOCK_MONOTONIC")?, + this.eval_libc_i32("CLOCK_MONOTONIC_COARSE")?, + ]; + } + "macos" => { + absolute_clocks = vec![this.eval_libc_i32("CLOCK_REALTIME")?]; + relative_clocks = vec![this.eval_libc_i32("CLOCK_MONOTONIC")?]; + // Some clocks only seem to exist in the aarch64 version of the target. + if this.tcx.sess.target.arch == "aarch64" { + // `CLOCK_UPTIME_RAW` supposed to not increment while the system is asleep... but + // that's not really something a program running inside Miri can tell, anyway. + // We need to support it because std uses it. + relative_clocks.push(this.eval_libc_i32("CLOCK_UPTIME_RAW")?); + } + } + target => throw_unsup_format!("`clock_gettime` is not supported on target OS {target}"), + } let duration = if absolute_clocks.contains(&clk_id) { this.check_no_isolation("`clock_gettime` with `REALTIME` clocks")?; @@ -44,6 +67,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } else if relative_clocks.contains(&clk_id) { this.machine.clock.now().duration_since(this.machine.clock.anchor()) } else { + // Unsupported clock. let einval = this.eval_libc("EINVAL")?; this.set_last_error(einval)?; return Ok(Scalar::from_i32(-1)); diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 44a433df1e9..d746f9df90a 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -180,6 +180,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let result = this.gettimeofday(tv, tz)?; this.write_scalar(Scalar::from_i32(result), dest)?; } + "clock_gettime" => { + let [clk_id, tp] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let result = this.clock_gettime(clk_id, tp)?; + this.write_scalar(result, dest)?; + } // Allocation "posix_memalign" => { diff --git a/src/tools/miri/src/shims/unix/linux/foreign_items.rs b/src/tools/miri/src/shims/unix/linux/foreign_items.rs index 2b53152688b..34076e842d5 100644 --- a/src/tools/miri/src/shims/unix/linux/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/linux/foreign_items.rs @@ -43,15 +43,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.write_scalar(result, dest)?; } - // Time related shims - "clock_gettime" => { - // This is a POSIX function but it has only been tested on linux. - let [clk_id, tp] = - this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let result = this.clock_gettime(clk_id, tp)?; - this.write_scalar(result, dest)?; - } - // Threading "pthread_condattr_setclock" => { let [attr, clock_id] = diff --git a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs index 904ae2fb17f..2a4300fcd04 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs @@ -181,17 +181,25 @@ fn test_thread_local_errno() { } /// Tests whether clock support exists at all -#[cfg(target_os = "linux")] fn test_clocks() { let mut tp = std::mem::MaybeUninit::::uninit(); let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME, tp.as_mut_ptr()) }; assert_eq!(is_error, 0); - let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME_COARSE, tp.as_mut_ptr()) }; - assert_eq!(is_error, 0); let is_error = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC, tp.as_mut_ptr()) }; assert_eq!(is_error, 0); - let is_error = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC_COARSE, tp.as_mut_ptr()) }; - assert_eq!(is_error, 0); + #[cfg(target_os = "linux")] + { + let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME_COARSE, tp.as_mut_ptr()) }; + assert_eq!(is_error, 0); + let is_error = + unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC_COARSE, tp.as_mut_ptr()) }; + assert_eq!(is_error, 0); + } + #[cfg(all(target_os = "macos", target_arch = "aarch64"))] + { + let is_error = unsafe { libc::clock_gettime(libc::CLOCK_UPTIME_RAW, tp.as_mut_ptr()) }; + assert_eq!(is_error, 0); + } } fn test_posix_gettimeofday() { @@ -293,11 +301,11 @@ fn main() { test_thread_local_errno(); test_isatty(); + test_clocks(); #[cfg(target_os = "linux")] { test_posix_fadvise(); test_sync_file_range(); - test_clocks(); } }