| author | bors <bors@rust-lang.org> 2024-02-17 11:44:02 UTC |
| committer | bors <bors@rust-lang.org> 2024-02-17 11:44:02 UTC |
| log | ba824a2e25948a86596ccf7594afe548020e86e6 |
| tree | 4bb2823fcd915a42bc7f10cef4d4f2b067e1ba36 |
| parent | dfdbe30004a095ad63951c4cd6e10a9a971a7399 |
| parent | e266a1230767cdbf1c1fd107e7caf0c67ab3e8c7 |
Rollup of 8 pull requests
Successful merges:
- #119032 (Use a hardcoded constant instead of calling OpenProcessToken.)
- #120932 (const_mut_refs: allow mutable pointers to statics)
- #121059 (Add and use a simple extension trait derive macro in the compiler)
- #121135 (coverage: Discard spans that fill the entire function body)
- #121187 (Add examples to document the return type of quickselect functions)
- #121191 (Add myself to review rotation (and a rustbot ping))
- #121192 (Give some intrinsics fallback bodies)
- #121197 (Ensure `./configure` works when `configure.py` path contains spaces)
r? `@ghost`
`@rustbot` modify labels: rollup65 files changed, 720 insertions(+), 1151 deletions(-)
compiler/rustc_ast_lowering/src/lib.rs+3-10| ... | ... | @@ -57,6 +57,7 @@ use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; |
| 57 | 57 | use rustc_hir::def_id::{LocalDefId, LocalDefIdMap, CRATE_DEF_ID, LOCAL_CRATE}; |
| 58 | 58 | use rustc_hir::{ConstArg, GenericArg, ItemLocalMap, ParamName, TraitCandidate}; |
| 59 | 59 | use rustc_index::{Idx, IndexSlice, IndexVec}; |
| 60 | use rustc_macros::extension; | |
| 60 | 61 | use rustc_middle::span_bug; |
| 61 | 62 | use rustc_middle::ty::{ResolverAstLowering, TyCtxt}; |
| 62 | 63 | use rustc_session::parse::{add_feature_diagnostics, feature_err}; |
| ... | ... | @@ -190,16 +191,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { |
| 190 | 191 | } |
| 191 | 192 | } |
| 192 | 193 | |
| 193 | trait ResolverAstLoweringExt { | |
| 194 | fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>>; | |
| 195 | fn get_partial_res(&self, id: NodeId) -> Option<PartialRes>; | |
| 196 | fn get_import_res(&self, id: NodeId) -> PerNS<Option<Res<NodeId>>>; | |
| 197 | fn get_label_res(&self, id: NodeId) -> Option<NodeId>; | |
| 198 | fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>; | |
| 199 | fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>; | |
| 200 | } | |
| 201 | ||
| 202 | impl ResolverAstLoweringExt for ResolverAstLowering { | |
| 194 | #[extension(trait ResolverAstLoweringExt)] | |
| 195 | impl ResolverAstLowering { | |
| 203 | 196 | fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>> { |
| 204 | 197 | if let ExprKind::Path(None, path) = &expr.kind { |
| 205 | 198 | // Don't perform legacy const generics rewriting if the path already |
compiler/rustc_borrowck/src/facts.rs+3-12| ... | ... | @@ -2,6 +2,7 @@ use crate::location::{LocationIndex, LocationTable}; |
| 2 | 2 | use crate::BorrowIndex; |
| 3 | 3 | use polonius_engine::AllFacts as PoloniusFacts; |
| 4 | 4 | use polonius_engine::Atom; |
| 5 | use rustc_macros::extension; | |
| 5 | 6 | use rustc_middle::mir::Local; |
| 6 | 7 | use rustc_middle::ty::{RegionVid, TyCtxt}; |
| 7 | 8 | use rustc_mir_dataflow::move_paths::MovePathIndex; |
| ... | ... | @@ -24,20 +25,10 @@ impl polonius_engine::FactTypes for RustcFacts { |
| 24 | 25 | |
| 25 | 26 | pub type AllFacts = PoloniusFacts<RustcFacts>; |
| 26 | 27 | |
| 27 | pub(crate) trait AllFactsExt { | |
| 28 | #[extension(pub(crate) trait AllFactsExt)] | |
| 29 | impl AllFacts { | |
| 28 | 30 | /// Returns `true` if there is a need to gather `AllFacts` given the |
| 29 | 31 | /// current `-Z` flags. |
| 30 | fn enabled(tcx: TyCtxt<'_>) -> bool; | |
| 31 | ||
| 32 | fn write_to_dir( | |
| 33 | &self, | |
| 34 | dir: impl AsRef<Path>, | |
| 35 | location_table: &LocationTable, | |
| 36 | ) -> Result<(), Box<dyn Error>>; | |
| 37 | } | |
| 38 | ||
| 39 | impl AllFactsExt for AllFacts { | |
| 40 | /// Return | |
| 41 | 32 | fn enabled(tcx: TyCtxt<'_>) -> bool { |
| 42 | 33 | tcx.sess.opts.unstable_opts.nll_facts |
| 43 | 34 | || tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() |
compiler/rustc_borrowck/src/place_ext.rs+3-11| ... | ... | @@ -1,24 +1,16 @@ |
| 1 | 1 | use crate::borrow_set::LocalsStateAtExit; |
| 2 | 2 | use rustc_hir as hir; |
| 3 | use rustc_macros::extension; | |
| 3 | 4 | use rustc_middle::mir::ProjectionElem; |
| 4 | 5 | use rustc_middle::mir::{Body, Mutability, Place}; |
| 5 | 6 | use rustc_middle::ty::{self, TyCtxt}; |
| 6 | 7 | |
| 7 | /// Extension methods for the `Place` type. | |
| 8 | pub trait PlaceExt<'tcx> { | |
| 8 | #[extension(pub trait PlaceExt<'tcx>)] | |
| 9 | impl<'tcx> Place<'tcx> { | |
| 9 | 10 | /// Returns `true` if we can safely ignore borrows of this place. |
| 10 | 11 | /// This is true whenever there is no action that the user can do |
| 11 | 12 | /// to the place `self` that would invalidate the borrow. This is true |
| 12 | 13 | /// for borrows of raw pointer dereferents as well as shared references. |
| 13 | fn ignore_borrow( | |
| 14 | &self, | |
| 15 | tcx: TyCtxt<'tcx>, | |
| 16 | body: &Body<'tcx>, | |
| 17 | locals_state_at_exit: &LocalsStateAtExit, | |
| 18 | ) -> bool; | |
| 19 | } | |
| 20 | ||
| 21 | impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { | |
| 22 | 14 | fn ignore_borrow( |
| 23 | 15 | &self, |
| 24 | 16 | tcx: TyCtxt<'tcx>, |
compiler/rustc_borrowck/src/region_infer/opaque_types.rs+3-9| ... | ... | @@ -6,6 +6,7 @@ use rustc_hir::OpaqueTyOrigin; |
| 6 | 6 | use rustc_infer::infer::InferCtxt; |
| 7 | 7 | use rustc_infer::infer::TyCtxtInferExt as _; |
| 8 | 8 | use rustc_infer::traits::{Obligation, ObligationCause}; |
| 9 | use rustc_macros::extension; | |
| 9 | 10 | use rustc_middle::traits::DefiningAnchor; |
| 10 | 11 | use rustc_middle::ty::visit::TypeVisitableExt; |
| 11 | 12 | use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable}; |
| ... | ... | @@ -225,15 +226,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { |
| 225 | 226 | } |
| 226 | 227 | } |
| 227 | 228 | |
| 228 | pub trait InferCtxtExt<'tcx> { | |
| 229 | fn infer_opaque_definition_from_instantiation( | |
| 230 | &self, | |
| 231 | opaque_type_key: OpaqueTypeKey<'tcx>, | |
| 232 | instantiated_ty: OpaqueHiddenType<'tcx>, | |
| 233 | ) -> Ty<'tcx>; | |
| 234 | } | |
| 235 | ||
| 236 | impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { | |
| 229 | #[extension(pub trait InferCtxtExt<'tcx>)] | |
| 230 | impl<'tcx> InferCtxt<'tcx> { | |
| 237 | 231 | /// Given the fully resolved, instantiated type for an opaque |
| 238 | 232 | /// type, i.e., the value of an inference variable like C1 or C2 |
| 239 | 233 | /// (*), computes the "definition type" for an opaque type |
compiler/rustc_borrowck/src/universal_regions.rs+3-21| ... | ... | @@ -22,6 +22,7 @@ use rustc_hir::lang_items::LangItem; |
| 22 | 22 | use rustc_hir::BodyOwnerKind; |
| 23 | 23 | use rustc_index::IndexVec; |
| 24 | 24 | use rustc_infer::infer::NllRegionVariableOrigin; |
| 25 | use rustc_macros::extension; | |
| 25 | 26 | use rustc_middle::ty::fold::TypeFoldable; |
| 26 | 27 | use rustc_middle::ty::print::with_no_trimmed_paths; |
| 27 | 28 | use rustc_middle::ty::{self, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, TyCtxt}; |
| ... | ... | @@ -793,27 +794,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { |
| 793 | 794 | } |
| 794 | 795 | } |
| 795 | 796 | |
| 796 | trait InferCtxtExt<'tcx> { | |
| 797 | fn replace_free_regions_with_nll_infer_vars<T>( | |
| 798 | &self, | |
| 799 | origin: NllRegionVariableOrigin, | |
| 800 | value: T, | |
| 801 | ) -> T | |
| 802 | where | |
| 803 | T: TypeFoldable<TyCtxt<'tcx>>; | |
| 804 | ||
| 805 | fn replace_bound_regions_with_nll_infer_vars<T>( | |
| 806 | &self, | |
| 807 | origin: NllRegionVariableOrigin, | |
| 808 | all_outlive_scope: LocalDefId, | |
| 809 | value: ty::Binder<'tcx, T>, | |
| 810 | indices: &mut UniversalRegionIndices<'tcx>, | |
| 811 | ) -> T | |
| 812 | where | |
| 813 | T: TypeFoldable<TyCtxt<'tcx>>; | |
| 814 | } | |
| 815 | ||
| 816 | impl<'cx, 'tcx> InferCtxtExt<'tcx> for BorrowckInferCtxt<'cx, 'tcx> { | |
| 797 | #[extension(trait InferCtxtExt<'tcx>)] | |
| 798 | impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> { | |
| 817 | 799 | #[instrument(skip(self), level = "debug")] |
| 818 | 800 | fn replace_free_regions_with_nll_infer_vars<T>( |
| 819 | 801 | &self, |
compiler/rustc_const_eval/src/transform/check_consts/check.rs+33-4| ... | ... | @@ -344,7 +344,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { |
| 344 | 344 | visitor.visit_ty(ty); |
| 345 | 345 | } |
| 346 | 346 | |
| 347 | fn check_mut_borrow(&mut self, local: Local, kind: hir::BorrowKind) { | |
| 347 | fn check_mut_borrow(&mut self, place: &Place<'_>, kind: hir::BorrowKind) { | |
| 348 | 348 | match self.const_kind() { |
| 349 | 349 | // In a const fn all borrows are transient or point to the places given via |
| 350 | 350 | // references in the arguments (so we already checked them with |
| ... | ... | @@ -355,10 +355,19 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { |
| 355 | 355 | // to mutable memory. |
| 356 | 356 | hir::ConstContext::ConstFn => self.check_op(ops::TransientMutBorrow(kind)), |
| 357 | 357 | _ => { |
| 358 | // For indirect places, we are not creating a new permanent borrow, it's just as | |
| 359 | // transient as the already existing one. For reborrowing references this is handled | |
| 360 | // at the top of `visit_rvalue`, but for raw pointers we handle it here. | |
| 361 | // Pointers/references to `static mut` and cases where the `*` is not the first | |
| 362 | // projection also end up here. | |
| 358 | 363 | // Locals with StorageDead do not live beyond the evaluation and can |
| 359 | 364 | // thus safely be borrowed without being able to be leaked to the final |
| 360 | 365 | // value of the constant. |
| 361 | if self.local_has_storage_dead(local) { | |
| 366 | // Note: This is only sound if every local that has a `StorageDead` has a | |
| 367 | // `StorageDead` in every control flow path leading to a `return` terminator. | |
| 368 | // The good news is that interning will detect if any unexpected mutable | |
| 369 | // pointer slips through. | |
| 370 | if place.is_indirect() || self.local_has_storage_dead(place.local) { | |
| 362 | 371 | self.check_op(ops::TransientMutBorrow(kind)); |
| 363 | 372 | } else { |
| 364 | 373 | self.check_op(ops::MutBorrow(kind)); |
| ... | ... | @@ -390,6 +399,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { |
| 390 | 399 | trace!("visit_rvalue: rvalue={:?} location={:?}", rvalue, location); |
| 391 | 400 | |
| 392 | 401 | // Special-case reborrows to be more like a copy of a reference. |
| 402 | // FIXME: this does not actually handle all reborrows. It only detects cases where `*` is the outermost | |
| 403 | // projection of the borrowed place, it skips deref'ing raw pointers and it skips `static`. | |
| 404 | // All those cases are handled below with shared/mutable borrows. | |
| 405 | // Once `const_mut_refs` is stable, we should be able to entirely remove this special case. | |
| 406 | // (`const_refs_to_cell` is not needed, we already allow all borrows of indirect places anyway.) | |
| 393 | 407 | match *rvalue { |
| 394 | 408 | Rvalue::Ref(_, kind, place) => { |
| 395 | 409 | if let Some(reborrowed_place_ref) = place_as_reborrow(self.tcx, self.body, place) { |
| ... | ... | @@ -460,7 +474,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { |
| 460 | 474 | |
| 461 | 475 | if !is_allowed { |
| 462 | 476 | self.check_mut_borrow( |
| 463 | place.local, | |
| 477 | place, | |
| 464 | 478 | if matches!(rvalue, Rvalue::Ref(..)) { |
| 465 | 479 | hir::BorrowKind::Ref |
| 466 | 480 | } else { |
| ... | ... | @@ -478,7 +492,14 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { |
| 478 | 492 | place.as_ref(), |
| 479 | 493 | ); |
| 480 | 494 | |
| 481 | if borrowed_place_has_mut_interior { | |
| 495 | // If the place is indirect, this is basically a reborrow. We have a reborrow | |
| 496 | // special case above, but for raw pointers and pointers/references to `static` and | |
| 497 | // when the `*` is not the first projection, `place_as_reborrow` does not recognize | |
| 498 | // them as such, so we end up here. This should probably be considered a | |
| 499 | // `TransientCellBorrow` (we consider the equivalent mutable case a | |
| 500 | // `TransientMutBorrow`), but such reborrows got accidentally stabilized already and | |
| 501 | // it is too much of a breaking change to take back. | |
| 502 | if borrowed_place_has_mut_interior && !place.is_indirect() { | |
| 482 | 503 | match self.const_kind() { |
| 483 | 504 | // In a const fn all borrows are transient or point to the places given via |
| 484 | 505 | // references in the arguments (so we already checked them with |
| ... | ... | @@ -495,6 +516,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { |
| 495 | 516 | // final value. |
| 496 | 517 | // Note: This is only sound if every local that has a `StorageDead` has a |
| 497 | 518 | // `StorageDead` in every control flow path leading to a `return` terminator. |
| 519 | // The good news is that interning will detect if any unexpected mutable | |
| 520 | // pointer slips through. | |
| 498 | 521 | if self.local_has_storage_dead(place.local) { |
| 499 | 522 | self.check_op(ops::TransientCellBorrow); |
| 500 | 523 | } else { |
| ... | ... | @@ -948,6 +971,12 @@ fn place_as_reborrow<'tcx>( |
| 948 | 971 | ) -> Option<PlaceRef<'tcx>> { |
| 949 | 972 | match place.as_ref().last_projection() { |
| 950 | 973 | Some((place_base, ProjectionElem::Deref)) => { |
| 974 | // FIXME: why do statics and raw pointers get excluded here? This makes | |
| 975 | // some code involving mutable pointers unstable, but it is unclear | |
| 976 | // why that code is treated differently from mutable references. | |
| 977 | // Once TransientMutBorrow and TransientCellBorrow are stable, | |
| 978 | // this can probably be cleaned up without any behavioral changes. | |
| 979 | ||
| 951 | 980 | // A borrow of a `static` also looks like `&(*_1)` in the MIR, but `_1` is a `const` |
| 952 | 981 | // that points to the allocation for the static. Don't treat these as reborrows. |
| 953 | 982 | if body.local_decls[place_base.local].is_ref_to_static() { |
compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs+24| ... | ... | @@ -74,6 +74,13 @@ pub trait Qualif { |
| 74 | 74 | adt: AdtDef<'tcx>, |
| 75 | 75 | args: GenericArgsRef<'tcx>, |
| 76 | 76 | ) -> bool; |
| 77 | ||
| 78 | /// Returns `true` if this `Qualif` behaves sructurally for pointers and references: | |
| 79 | /// the pointer/reference qualifies if and only if the pointee qualifies. | |
| 80 | /// | |
| 81 | /// (This is currently `false` for all our instances, but that may change in the future. Also, | |
| 82 | /// by keeping it abstract, the handling of `Deref` in `in_place` becomes more clear.) | |
| 83 | fn deref_structural<'tcx>(cx: &ConstCx<'_, 'tcx>) -> bool; | |
| 77 | 84 | } |
| 78 | 85 | |
| 79 | 86 | /// Constant containing interior mutability (`UnsafeCell<T>`). |
| ... | ... | @@ -103,6 +110,10 @@ impl Qualif for HasMutInterior { |
| 103 | 110 | // It arises structurally for all other types. |
| 104 | 111 | adt.is_unsafe_cell() |
| 105 | 112 | } |
| 113 | ||
| 114 | fn deref_structural<'tcx>(_cx: &ConstCx<'_, 'tcx>) -> bool { | |
| 115 | false | |
| 116 | } | |
| 106 | 117 | } |
| 107 | 118 | |
| 108 | 119 | /// Constant containing an ADT that implements `Drop`. |
| ... | ... | @@ -131,6 +142,10 @@ impl Qualif for NeedsDrop { |
| 131 | 142 | ) -> bool { |
| 132 | 143 | adt.has_dtor(cx.tcx) |
| 133 | 144 | } |
| 145 | ||
| 146 | fn deref_structural<'tcx>(_cx: &ConstCx<'_, 'tcx>) -> bool { | |
| 147 | false | |
| 148 | } | |
| 134 | 149 | } |
| 135 | 150 | |
| 136 | 151 | /// Constant containing an ADT that implements non-const `Drop`. |
| ... | ... | @@ -210,6 +225,10 @@ impl Qualif for NeedsNonConstDrop { |
| 210 | 225 | ) -> bool { |
| 211 | 226 | adt.has_non_const_dtor(cx.tcx) |
| 212 | 227 | } |
| 228 | ||
| 229 | fn deref_structural<'tcx>(_cx: &ConstCx<'_, 'tcx>) -> bool { | |
| 230 | false | |
| 231 | } | |
| 213 | 232 | } |
| 214 | 233 | |
| 215 | 234 | // FIXME: Use `mir::visit::Visitor` for the `in_*` functions if/when it supports early return. |
| ... | ... | @@ -303,6 +322,11 @@ where |
| 303 | 322 | return false; |
| 304 | 323 | } |
| 305 | 324 | |
| 325 | if matches!(elem, ProjectionElem::Deref) && !Q::deref_structural(cx) { | |
| 326 | // We have to assume that this qualifies. | |
| 327 | return true; | |
| 328 | } | |
| 329 | ||
| 306 | 330 | place = place_base; |
| 307 | 331 | } |
| 308 | 332 |
compiler/rustc_hir_analysis/src/check/intrinsic.rs+3-3| ... | ... | @@ -407,9 +407,9 @@ pub fn check_intrinsic_type( |
| 407 | 407 | } |
| 408 | 408 | sym::float_to_int_unchecked => (2, 0, vec![param(0)], param(1)), |
| 409 | 409 | |
| 410 | sym::assume => (0, 0, vec![tcx.types.bool], Ty::new_unit(tcx)), | |
| 411 | sym::likely => (0, 0, vec![tcx.types.bool], tcx.types.bool), | |
| 412 | sym::unlikely => (0, 0, vec![tcx.types.bool], tcx.types.bool), | |
| 410 | sym::assume => (0, 1, vec![tcx.types.bool], Ty::new_unit(tcx)), | |
| 411 | sym::likely => (0, 1, vec![tcx.types.bool], tcx.types.bool), | |
| 412 | sym::unlikely => (0, 1, vec![tcx.types.bool], tcx.types.bool), | |
| 413 | 413 | |
| 414 | 414 | sym::read_via_copy => (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], param(0)), |
| 415 | 415 | sym::write_via_move => { |
compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs+3-11| ... | ... | @@ -14,6 +14,7 @@ use rustc_hir::def::{DefKind, Res}; |
| 14 | 14 | use rustc_hir::def_id::LocalDefId; |
| 15 | 15 | use rustc_hir::intravisit::{self, Visitor}; |
| 16 | 16 | use rustc_hir::{GenericArg, GenericParam, GenericParamKind, HirIdMap, LifetimeName, Node}; |
| 17 | use rustc_macros::extension; | |
| 17 | 18 | use rustc_middle::bug; |
| 18 | 19 | use rustc_middle::hir::nested_filter; |
| 19 | 20 | use rustc_middle::middle::resolve_bound_vars::*; |
| ... | ... | @@ -27,17 +28,8 @@ use std::fmt; |
| 27 | 28 | |
| 28 | 29 | use crate::errors; |
| 29 | 30 | |
| 30 | trait RegionExt { | |
| 31 | fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg); | |
| 32 | ||
| 33 | fn late(index: u32, param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg); | |
| 34 | ||
| 35 | fn id(&self) -> Option<DefId>; | |
| 36 | ||
| 37 | fn shifted(self, amount: u32) -> ResolvedArg; | |
| 38 | } | |
| 39 | ||
| 40 | impl RegionExt for ResolvedArg { | |
| 31 | #[extension(trait RegionExt)] | |
| 32 | impl ResolvedArg { | |
| 41 | 33 | fn early(param: &GenericParam<'_>) -> (LocalDefId, ResolvedArg) { |
| 42 | 34 | debug!("ResolvedArg::early: def_id={:?}", param.def_id); |
| 43 | 35 | (param.def_id, ResolvedArg::EarlyBound(param.def_id.to_def_id())) |
compiler/rustc_infer/src/infer/canonical/instantiate.rs+6-20| ... | ... | @@ -13,12 +13,16 @@ use rustc_middle::ty::{self, TyCtxt}; |
| 13 | 13 | |
| 14 | 14 | /// FIXME(-Znext-solver): This or public because it is shared with the |
| 15 | 15 | /// new trait solver implementation. We should deduplicate canonicalization. |
| 16 | pub trait CanonicalExt<'tcx, V> { | |
| 16 | #[extension(pub trait CanonicalExt<'tcx, V>)] | |
| 17 | impl<'tcx, V> Canonical<'tcx, V> { | |
| 17 | 18 | /// Instantiate the wrapped value, replacing each canonical value |
| 18 | 19 | /// with the value given in `var_values`. |
| 19 | 20 | fn instantiate(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V |
| 20 | 21 | where |
| 21 | V: TypeFoldable<TyCtxt<'tcx>>; | |
| 22 | V: TypeFoldable<TyCtxt<'tcx>>, | |
| 23 | { | |
| 24 | self.instantiate_projected(tcx, var_values, |value| value.clone()) | |
| 25 | } | |
| 22 | 26 | |
| 23 | 27 | /// Allows one to apply a instantiation to some subset of |
| 24 | 28 | /// `self.value`. Invoke `projection_fn` with `self.value` to get |
| ... | ... | @@ -26,24 +30,6 @@ pub trait CanonicalExt<'tcx, V> { |
| 26 | 30 | /// variables bound in `self` (usually this extracts from subset |
| 27 | 31 | /// of `self`). Apply the instantiation `var_values` to this value |
| 28 | 32 | /// V, replacing each of the canonical variables. |
| 29 | fn instantiate_projected<T>( | |
| 30 | &self, | |
| 31 | tcx: TyCtxt<'tcx>, | |
| 32 | var_values: &CanonicalVarValues<'tcx>, | |
| 33 | projection_fn: impl FnOnce(&V) -> T, | |
| 34 | ) -> T | |
| 35 | where | |
| 36 | T: TypeFoldable<TyCtxt<'tcx>>; | |
| 37 | } | |
| 38 | ||
| 39 | impl<'tcx, V> CanonicalExt<'tcx, V> for Canonical<'tcx, V> { | |
| 40 | fn instantiate(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V | |
| 41 | where | |
| 42 | V: TypeFoldable<TyCtxt<'tcx>>, | |
| 43 | { | |
| 44 | self.instantiate_projected(tcx, var_values, |value| value.clone()) | |
| 45 | } | |
| 46 | ||
| 47 | 33 | fn instantiate_projected<T>( |
| 48 | 34 | &self, |
| 49 | 35 | tcx: TyCtxt<'tcx>, |
compiler/rustc_infer/src/infer/error_reporting/mod.rs+2-13| ... | ... | @@ -2786,19 +2786,8 @@ pub enum FailureCode { |
| 2786 | 2786 | Error0644, |
| 2787 | 2787 | } |
| 2788 | 2788 | |
| 2789 | pub trait ObligationCauseExt<'tcx> { | |
| 2790 | fn as_failure_code(&self, terr: TypeError<'tcx>) -> FailureCode; | |
| 2791 | ||
| 2792 | fn as_failure_code_diag( | |
| 2793 | &self, | |
| 2794 | terr: TypeError<'tcx>, | |
| 2795 | span: Span, | |
| 2796 | subdiags: Vec<TypeErrorAdditionalDiags>, | |
| 2797 | ) -> ObligationCauseFailureCode; | |
| 2798 | fn as_requirement_str(&self) -> &'static str; | |
| 2799 | } | |
| 2800 | ||
| 2801 | impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { | |
| 2789 | #[extension(pub trait ObligationCauseExt<'tcx>)] | |
| 2790 | impl<'tcx> ObligationCause<'tcx> { | |
| 2802 | 2791 | fn as_failure_code(&self, terr: TypeError<'tcx>) -> FailureCode { |
| 2803 | 2792 | use self::FailureCode::*; |
| 2804 | 2793 | use crate::traits::ObligationCauseCode::*; |
compiler/rustc_infer/src/infer/mod.rs+2-5| ... | ... | @@ -626,11 +626,8 @@ pub struct InferCtxtBuilder<'tcx> { |
| 626 | 626 | next_trait_solver: bool, |
| 627 | 627 | } |
| 628 | 628 | |
| 629 | pub trait TyCtxtInferExt<'tcx> { | |
| 630 | fn infer_ctxt(self) -> InferCtxtBuilder<'tcx>; | |
| 631 | } | |
| 632 | ||
| 633 | impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { | |
| 629 | #[extension(pub trait TyCtxtInferExt<'tcx>)] | |
| 630 | impl<'tcx> TyCtxt<'tcx> { | |
| 634 | 631 | fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { |
| 635 | 632 | InferCtxtBuilder { |
| 636 | 633 | tcx: self, |
compiler/rustc_infer/src/traits/engine.rs+3-12| ... | ... | @@ -52,18 +52,8 @@ pub trait TraitEngine<'tcx>: 'tcx { |
| 52 | 52 | ) -> Vec<PredicateObligation<'tcx>>; |
| 53 | 53 | } |
| 54 | 54 | |
| 55 | pub trait TraitEngineExt<'tcx> { | |
| 56 | fn register_predicate_obligations( | |
| 57 | &mut self, | |
| 58 | infcx: &InferCtxt<'tcx>, | |
| 59 | obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>, | |
| 60 | ); | |
| 61 | ||
| 62 | #[must_use] | |
| 63 | fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>; | |
| 64 | } | |
| 65 | ||
| 66 | impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T { | |
| 55 | #[extension(pub trait TraitEngineExt<'tcx>)] | |
| 56 | impl<'tcx, T: ?Sized + TraitEngine<'tcx>> T { | |
| 67 | 57 | fn register_predicate_obligations( |
| 68 | 58 | &mut self, |
| 69 | 59 | infcx: &InferCtxt<'tcx>, |
| ... | ... | @@ -74,6 +64,7 @@ impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T { |
| 74 | 64 | } |
| 75 | 65 | } |
| 76 | 66 | |
| 67 | #[must_use] | |
| 77 | 68 | fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> { |
| 78 | 69 | let errors = self.select_where_possible(infcx); |
| 79 | 70 | if !errors.is_empty() { |
compiler/rustc_macros/src/extension.rs created+154| ... | ... | @@ -0,0 +1,154 @@ |
| 1 | use proc_macro2::Ident; | |
| 2 | use quote::quote; | |
| 3 | use syn::parse::{Parse, ParseStream}; | |
| 4 | use syn::punctuated::Punctuated; | |
| 5 | use syn::spanned::Spanned; | |
| 6 | use syn::{ | |
| 7 | braced, parse_macro_input, Attribute, Generics, ImplItem, Pat, PatIdent, Path, Signature, | |
| 8 | Token, TraitItem, TraitItemConst, TraitItemFn, TraitItemMacro, TraitItemType, Type, Visibility, | |
| 9 | }; | |
| 10 | ||
| 11 | pub(crate) fn extension( | |
| 12 | attr: proc_macro::TokenStream, | |
| 13 | input: proc_macro::TokenStream, | |
| 14 | ) -> proc_macro::TokenStream { | |
| 15 | let ExtensionAttr { vis, trait_ } = parse_macro_input!(attr as ExtensionAttr); | |
| 16 | let Impl { attrs, generics, self_ty, items } = parse_macro_input!(input as Impl); | |
| 17 | let headers: Vec<_> = items | |
| 18 | .iter() | |
| 19 | .map(|item| match item { | |
| 20 | ImplItem::Fn(f) => TraitItem::Fn(TraitItemFn { | |
| 21 | attrs: scrub_attrs(&f.attrs), | |
| 22 | sig: scrub_header(f.sig.clone()), | |
| 23 | default: None, | |
| 24 | semi_token: Some(Token)), | |
| 25 | }), | |
| 26 | ImplItem::Const(ct) => TraitItem::Const(TraitItemConst { | |
| 27 | attrs: scrub_attrs(&ct.attrs), | |
| 28 | const_token: ct.const_token, | |
| 29 | ident: ct.ident.clone(), | |
| 30 | generics: ct.generics.clone(), | |
| 31 | colon_token: ct.colon_token, | |
| 32 | ty: ct.ty.clone(), | |
| 33 | default: None, | |
| 34 | semi_token: ct.semi_token, | |
| 35 | }), | |
| 36 | ImplItem::Type(ty) => TraitItem::Type(TraitItemType { | |
| 37 | attrs: scrub_attrs(&ty.attrs), | |
| 38 | type_token: ty.type_token, | |
| 39 | ident: ty.ident.clone(), | |
| 40 | generics: ty.generics.clone(), | |
| 41 | colon_token: None, | |
| 42 | bounds: Punctuated::new(), | |
| 43 | default: None, | |
| 44 | semi_token: ty.semi_token, | |
| 45 | }), | |
| 46 | ImplItem::Macro(mac) => TraitItem::Macro(TraitItemMacro { | |
| 47 | attrs: scrub_attrs(&mac.attrs), | |
| 48 | mac: mac.mac.clone(), | |
| 49 | semi_token: mac.semi_token, | |
| 50 | }), | |
| 51 | ImplItem::Verbatim(stream) => TraitItem::Verbatim(stream.clone()), | |
| 52 | _ => unimplemented!(), | |
| 53 | }) | |
| 54 | .collect(); | |
| 55 | ||
| 56 | quote! { | |
| 57 | #(#attrs)* | |
| 58 | #vis trait #trait_ { | |
| 59 | #(#headers)* | |
| 60 | } | |
| 61 | ||
| 62 | impl #generics #trait_ for #self_ty { | |
| 63 | #(#items)* | |
| 64 | } | |
| 65 | } | |
| 66 | .into() | |
| 67 | } | |
| 68 | ||
| 69 | /// Only keep `#[doc]` attrs. | |
| 70 | fn scrub_attrs(attrs: &[Attribute]) -> Vec<Attribute> { | |
| 71 | attrs | |
| 72 | .into_iter() | |
| 73 | .cloned() | |
| 74 | .filter(|attr| { | |
| 75 | let ident = &attr.path().segments[0].ident; | |
| 76 | ident == "doc" || ident == "must_use" | |
| 77 | }) | |
| 78 | .collect() | |
| 79 | } | |
| 80 | ||
| 81 | /// Scrub arguments so that they're valid for trait signatures. | |
| 82 | fn scrub_header(mut sig: Signature) -> Signature { | |
| 83 | for (idx, input) in sig.inputs.iter_mut().enumerate() { | |
| 84 | match input { | |
| 85 | syn::FnArg::Receiver(rcvr) => { | |
| 86 | // `mut self` -> `self` | |
| 87 | if rcvr.reference.is_none() { | |
| 88 | rcvr.mutability.take(); | |
| 89 | } | |
| 90 | } | |
| 91 | syn::FnArg::Typed(arg) => match &mut *arg.pat { | |
| 92 | Pat::Ident(arg) => { | |
| 93 | // `ref mut ident @ pat` -> `ident` | |
| 94 | arg.by_ref.take(); | |
| 95 | arg.mutability.take(); | |
| 96 | arg.subpat.take(); | |
| 97 | } | |
| 98 | _ => { | |
| 99 | // `pat` -> `__arg0` | |
| 100 | arg.pat = Box::new( | |
| 101 | PatIdent { | |
| 102 | attrs: vec![], | |
| 103 | by_ref: None, | |
| 104 | mutability: None, | |
| 105 | ident: Ident::new(&format!("__arg{idx}"), arg.pat.span()), | |
| 106 | subpat: None, | |
| 107 | } | |
| 108 | .into(), | |
| 109 | ) | |
| 110 | } | |
| 111 | }, | |
| 112 | } | |
| 113 | } | |
| 114 | sig | |
| 115 | } | |
| 116 | ||
| 117 | struct ExtensionAttr { | |
| 118 | vis: Visibility, | |
| 119 | trait_: Path, | |
| 120 | } | |
| 121 | ||
| 122 | impl Parse for ExtensionAttr { | |
| 123 | fn parse(input: ParseStream<'_>) -> syn::Result<Self> { | |
| 124 | let vis = input.parse()?; | |
| 125 | let _: Token![trait] = input.parse()?; | |
| 126 | let trait_ = input.parse()?; | |
| 127 | Ok(ExtensionAttr { vis, trait_ }) | |
| 128 | } | |
| 129 | } | |
| 130 | ||
| 131 | struct Impl { | |
| 132 | attrs: Vec<Attribute>, | |
| 133 | generics: Generics, | |
| 134 | self_ty: Type, | |
| 135 | items: Vec<ImplItem>, | |
| 136 | } | |
| 137 | ||
| 138 | impl Parse for Impl { | |
| 139 | fn parse(input: ParseStream<'_>) -> syn::Result<Self> { | |
| 140 | let attrs = input.call(Attribute::parse_outer)?; | |
| 141 | let _: Token![impl] = input.parse()?; | |
| 142 | let generics = input.parse()?; | |
| 143 | let self_ty = input.parse()?; | |
| 144 | ||
| 145 | let content; | |
| 146 | let _brace_token = braced!(content in input); | |
| 147 | let mut items = Vec::new(); | |
| 148 | while !content.is_empty() { | |
| 149 | items.push(content.parse()?); | |
| 150 | } | |
| 151 | ||
| 152 | Ok(Impl { attrs, generics, self_ty, items }) | |
| 153 | } | |
| 154 | } |
compiler/rustc_macros/src/lib.rs+6| ... | ... | @@ -14,6 +14,7 @@ use proc_macro::TokenStream; |
| 14 | 14 | |
| 15 | 15 | mod current_version; |
| 16 | 16 | mod diagnostics; |
| 17 | mod extension; | |
| 17 | 18 | mod hash_stable; |
| 18 | 19 | mod lift; |
| 19 | 20 | mod query; |
| ... | ... | @@ -40,6 +41,11 @@ pub fn symbols(input: TokenStream) -> TokenStream { |
| 40 | 41 | symbols::symbols(input.into()).into() |
| 41 | 42 | } |
| 42 | 43 | |
| 44 | #[proc_macro_attribute] | |
| 45 | pub fn extension(attr: TokenStream, input: TokenStream) -> TokenStream { | |
| 46 | extension::extension(attr, input) | |
| 47 | } | |
| 48 | ||
| 43 | 49 | decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive); |
| 44 | 50 | decl_derive!( |
| 45 | 51 | [HashStable_Generic, attributes(stable_hasher)] => |
compiler/rustc_middle/src/ty/layout.rs+4-20| ... | ... | @@ -23,20 +23,8 @@ use std::fmt; |
| 23 | 23 | use std::num::NonZero; |
| 24 | 24 | use std::ops::Bound; |
| 25 | 25 | |
| 26 | pub trait IntegerExt { | |
| 27 | fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>; | |
| 28 | fn from_int_ty<C: HasDataLayout>(cx: &C, ity: ty::IntTy) -> Integer; | |
| 29 | fn from_uint_ty<C: HasDataLayout>(cx: &C, uty: ty::UintTy) -> Integer; | |
| 30 | fn repr_discr<'tcx>( | |
| 31 | tcx: TyCtxt<'tcx>, | |
| 32 | ty: Ty<'tcx>, | |
| 33 | repr: &ReprOptions, | |
| 34 | min: i128, | |
| 35 | max: i128, | |
| 36 | ) -> (Integer, bool); | |
| 37 | } | |
| 38 | ||
| 39 | impl IntegerExt for Integer { | |
| 26 | #[extension(pub trait IntegerExt)] | |
| 27 | impl Integer { | |
| 40 | 28 | #[inline] |
| 41 | 29 | fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx> { |
| 42 | 30 | match (*self, signed) { |
| ... | ... | @@ -123,12 +111,8 @@ impl IntegerExt for Integer { |
| 123 | 111 | } |
| 124 | 112 | } |
| 125 | 113 | |
| 126 | pub trait PrimitiveExt { | |
| 127 | fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>; | |
| 128 | fn to_int_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>; | |
| 129 | } | |
| 130 | ||
| 131 | impl PrimitiveExt for Primitive { | |
| 114 | #[extension(pub trait PrimitiveExt)] | |
| 115 | impl Primitive { | |
| 132 | 116 | #[inline] |
| 133 | 117 | fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { |
| 134 | 118 | match *self { |
compiler/rustc_middle/src/ty/util.rs+2-7| ... | ... | @@ -96,13 +96,8 @@ impl<'tcx> Discr<'tcx> { |
| 96 | 96 | } |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | pub trait IntTypeExt { | |
| 100 | fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx>; | |
| 101 | fn disr_incr<'tcx>(&self, tcx: TyCtxt<'tcx>, val: Option<Discr<'tcx>>) -> Option<Discr<'tcx>>; | |
| 102 | fn initial_discriminant<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Discr<'tcx>; | |
| 103 | } | |
| 104 | ||
| 105 | impl IntTypeExt for IntegerType { | |
| 99 | #[extension(pub trait IntTypeExt)] | |
| 100 | impl IntegerType { | |
| 106 | 101 | fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { |
| 107 | 102 | match self { |
| 108 | 103 | IntegerType::Pointer(true) => tcx.types.isize, |
compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs+9-4| ... | ... | @@ -132,18 +132,23 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>( |
| 132 | 132 | bcb_data.basic_blocks.iter().flat_map(move |&bb| { |
| 133 | 133 | let data = &mir_body[bb]; |
| 134 | 134 | |
| 135 | let unexpand = move |expn_span| { | |
| 136 | unexpand_into_body_span_with_visible_macro(expn_span, body_span) | |
| 137 | // Discard any spans that fill the entire body, because they tend | |
| 138 | // to represent compiler-inserted code, e.g. implicitly returning `()`. | |
| 139 | .filter(|(span, _)| !span.source_equal(body_span)) | |
| 140 | }; | |
| 141 | ||
| 135 | 142 | let statement_spans = data.statements.iter().filter_map(move |statement| { |
| 136 | 143 | let expn_span = filtered_statement_span(statement)?; |
| 137 | let (span, visible_macro) = | |
| 138 | unexpand_into_body_span_with_visible_macro(expn_span, body_span)?; | |
| 144 | let (span, visible_macro) = unexpand(expn_span)?; | |
| 139 | 145 | |
| 140 | 146 | Some(SpanFromMir::new(span, visible_macro, bcb, is_closure_like(statement))) |
| 141 | 147 | }); |
| 142 | 148 | |
| 143 | 149 | let terminator_span = Some(data.terminator()).into_iter().filter_map(move |terminator| { |
| 144 | 150 | let expn_span = filtered_terminator_span(terminator)?; |
| 145 | let (span, visible_macro) = | |
| 146 | unexpand_into_body_span_with_visible_macro(expn_span, body_span)?; | |
| 151 | let (span, visible_macro) = unexpand(expn_span)?; | |
| 147 | 152 | |
| 148 | 153 | Some(SpanFromMir::new(span, visible_macro, bcb, false)) |
| 149 | 154 | }); |
compiler/rustc_trait_selection/src/infer.rs+26-56| ... | ... | @@ -17,49 +17,8 @@ use std::fmt::Debug; |
| 17 | 17 | |
| 18 | 18 | pub use rustc_infer::infer::*; |
| 19 | 19 | |
| 20 | pub trait InferCtxtExt<'tcx> { | |
| 21 | fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool; | |
| 22 | ||
| 23 | fn type_is_sized_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool; | |
| 24 | ||
| 25 | /// Check whether a `ty` implements given trait(trait_def_id) without side-effects. | |
| 26 | /// | |
| 27 | /// The inputs are: | |
| 28 | /// | |
| 29 | /// - the def-id of the trait | |
| 30 | /// - the type parameters of the trait, including the self-type | |
| 31 | /// - the parameter environment | |
| 32 | /// | |
| 33 | /// Invokes `evaluate_obligation`, so in the event that evaluating | |
| 34 | /// `Ty: Trait` causes overflow, EvaluatedToErrStackDependent | |
| 35 | /// (or EvaluatedToAmbigStackDependent) will be returned. | |
| 36 | fn type_implements_trait( | |
| 37 | &self, | |
| 38 | trait_def_id: DefId, | |
| 39 | params: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, | |
| 40 | param_env: ty::ParamEnv<'tcx>, | |
| 41 | ) -> traits::EvaluationResult; | |
| 42 | ||
| 43 | /// Returns `Some` if a type implements a trait shallowly, without side-effects, | |
| 44 | /// along with any errors that would have been reported upon further obligation | |
| 45 | /// processing. | |
| 46 | /// | |
| 47 | /// - If this returns `Some([])`, then the trait holds modulo regions. | |
| 48 | /// - If this returns `Some([errors..])`, then the trait has an impl for | |
| 49 | /// the self type, but some nested obligations do not hold. | |
| 50 | /// - If this returns `None`, no implementation that applies could be found. | |
| 51 | /// | |
| 52 | /// FIXME(-Znext-solver): Due to the recursive nature of the new solver, | |
| 53 | /// this will probably only ever return `Some([])` or `None`. | |
| 54 | fn type_implements_trait_shallow( | |
| 55 | &self, | |
| 56 | trait_def_id: DefId, | |
| 57 | ty: Ty<'tcx>, | |
| 58 | param_env: ty::ParamEnv<'tcx>, | |
| 59 | ) -> Option<Vec<traits::FulfillmentError<'tcx>>>; | |
| 60 | } | |
| 61 | ||
| 62 | impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { | |
| 20 | #[extension(pub trait InferCtxtExt<'tcx>)] | |
| 21 | impl<'tcx> InferCtxt<'tcx> { | |
| 63 | 22 | fn type_is_copy_modulo_regions(&self, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { |
| 64 | 23 | let ty = self.resolve_vars_if_possible(ty); |
| 65 | 24 | |
| ... | ... | @@ -81,6 +40,17 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { |
| 81 | 40 | traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, lang_item) |
| 82 | 41 | } |
| 83 | 42 | |
| 43 | /// Check whether a `ty` implements given trait(trait_def_id) without side-effects. | |
| 44 | /// | |
| 45 | /// The inputs are: | |
| 46 | /// | |
| 47 | /// - the def-id of the trait | |
| 48 | /// - the type parameters of the trait, including the self-type | |
| 49 | /// - the parameter environment | |
| 50 | /// | |
| 51 | /// Invokes `evaluate_obligation`, so in the event that evaluating | |
| 52 | /// `Ty: Trait` causes overflow, EvaluatedToErrStackDependent | |
| 53 | /// (or EvaluatedToAmbigStackDependent) will be returned. | |
| 84 | 54 | #[instrument(level = "debug", skip(self, params), ret)] |
| 85 | 55 | fn type_implements_trait( |
| 86 | 56 | &self, |
| ... | ... | @@ -99,6 +69,17 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { |
| 99 | 69 | self.evaluate_obligation(&obligation).unwrap_or(traits::EvaluationResult::EvaluatedToErr) |
| 100 | 70 | } |
| 101 | 71 | |
| 72 | /// Returns `Some` if a type implements a trait shallowly, without side-effects, | |
| 73 | /// along with any errors that would have been reported upon further obligation | |
| 74 | /// processing. | |
| 75 | /// | |
| 76 | /// - If this returns `Some([])`, then the trait holds modulo regions. | |
| 77 | /// - If this returns `Some([errors..])`, then the trait has an impl for | |
| 78 | /// the self type, but some nested obligations do not hold. | |
| 79 | /// - If this returns `None`, no implementation that applies could be found. | |
| 80 | /// | |
| 81 | /// FIXME(-Znext-solver): Due to the recursive nature of the new solver, | |
| 82 | /// this will probably only ever return `Some([])` or `None`. | |
| 102 | 83 | fn type_implements_trait_shallow( |
| 103 | 84 | &self, |
| 104 | 85 | trait_def_id: DefId, |
| ... | ... | @@ -124,19 +105,8 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { |
| 124 | 105 | } |
| 125 | 106 | } |
| 126 | 107 | |
| 127 | pub trait InferCtxtBuilderExt<'tcx> { | |
| 128 | fn enter_canonical_trait_query<K, R>( | |
| 129 | self, | |
| 130 | canonical_key: &Canonical<'tcx, K>, | |
| 131 | operation: impl FnOnce(&ObligationCtxt<'_, 'tcx>, K) -> Result<R, NoSolution>, | |
| 132 | ) -> Result<CanonicalQueryResponse<'tcx, R>, NoSolution> | |
| 133 | where | |
| 134 | K: TypeFoldable<TyCtxt<'tcx>>, | |
| 135 | R: Debug + TypeFoldable<TyCtxt<'tcx>>, | |
| 136 | Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>; | |
| 137 | } | |
| 138 | ||
| 139 | impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> { | |
| 108 | #[extension(pub trait InferCtxtBuilderExt<'tcx>)] | |
| 109 | impl<'tcx> InferCtxtBuilder<'tcx> { | |
| 140 | 110 | /// The "main method" for a canonicalized trait query. Given the |
| 141 | 111 | /// canonical key `canonical_key`, this method will create a new |
| 142 | 112 | /// inference context, instantiate the key, and run your operation |
compiler/rustc_trait_selection/src/regions.rs+2-8| ... | ... | @@ -3,20 +3,14 @@ use rustc_infer::infer::{InferCtxt, RegionResolutionError}; |
| 3 | 3 | use rustc_middle::traits::query::NoSolution; |
| 4 | 4 | use rustc_middle::traits::ObligationCause; |
| 5 | 5 | |
| 6 | pub trait InferCtxtRegionExt<'tcx> { | |
| 6 | #[extension(pub trait InferCtxtRegionExt<'tcx>)] | |
| 7 | impl<'tcx> InferCtxt<'tcx> { | |
| 7 | 8 | /// Resolve regions, using the deep normalizer to normalize any type-outlives |
| 8 | 9 | /// obligations in the process. This is in `rustc_trait_selection` because |
| 9 | 10 | /// we need to normalize. |
| 10 | 11 | /// |
| 11 | 12 | /// Prefer this method over `resolve_regions_with_normalize`, unless you are |
| 12 | 13 | /// doing something specific for normalization. |
| 13 | fn resolve_regions( | |
| 14 | &self, | |
| 15 | outlives_env: &OutlivesEnvironment<'tcx>, | |
| 16 | ) -> Vec<RegionResolutionError<'tcx>>; | |
| 17 | } | |
| 18 | ||
| 19 | impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> { | |
| 20 | 14 | fn resolve_regions( |
| 21 | 15 | &self, |
| 22 | 16 | outlives_env: &OutlivesEnvironment<'tcx>, |
compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs+2-12| ... | ... | @@ -131,22 +131,12 @@ pub enum GenerateProofTree { |
| 131 | 131 | Never, |
| 132 | 132 | } |
| 133 | 133 | |
| 134 | pub trait InferCtxtEvalExt<'tcx> { | |
| 134 | #[extension(pub trait InferCtxtEvalExt<'tcx>)] | |
| 135 | impl<'tcx> InferCtxt<'tcx> { | |
| 135 | 136 | /// Evaluates a goal from **outside** of the trait solver. |
| 136 | 137 | /// |
| 137 | 138 | /// Using this while inside of the solver is wrong as it uses a new |
| 138 | 139 | /// search graph which would break cycle detection. |
| 139 | fn evaluate_root_goal( | |
| 140 | &self, | |
| 141 | goal: Goal<'tcx, ty::Predicate<'tcx>>, | |
| 142 | generate_proof_tree: GenerateProofTree, | |
| 143 | ) -> ( | |
| 144 | Result<(bool, Certainty, Vec<Goal<'tcx, ty::Predicate<'tcx>>>), NoSolution>, | |
| 145 | Option<inspect::GoalEvaluation<'tcx>>, | |
| 146 | ); | |
| 147 | } | |
| 148 | ||
| 149 | impl<'tcx> InferCtxtEvalExt<'tcx> for InferCtxt<'tcx> { | |
| 150 | 140 | #[instrument(level = "debug", skip(self))] |
| 151 | 141 | fn evaluate_root_goal( |
| 152 | 142 | &self, |
compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs+2-8| ... | ... | @@ -17,14 +17,8 @@ use crate::solve::inspect::ProofTreeBuilder; |
| 17 | 17 | use crate::traits::StructurallyNormalizeExt; |
| 18 | 18 | use crate::traits::TraitEngineExt; |
| 19 | 19 | |
| 20 | pub trait InferCtxtSelectExt<'tcx> { | |
| 21 | fn select_in_new_trait_solver( | |
| 22 | &self, | |
| 23 | obligation: &PolyTraitObligation<'tcx>, | |
| 24 | ) -> SelectionResult<'tcx, Selection<'tcx>>; | |
| 25 | } | |
| 26 | ||
| 27 | impl<'tcx> InferCtxtSelectExt<'tcx> for InferCtxt<'tcx> { | |
| 20 | #[extension(pub trait InferCtxtSelectExt<'tcx>)] | |
| 21 | impl<'tcx> InferCtxt<'tcx> { | |
| 28 | 22 | fn select_in_new_trait_solver( |
| 29 | 23 | &self, |
| 30 | 24 | obligation: &PolyTraitObligation<'tcx>, |
compiler/rustc_trait_selection/src/solve/inspect/analyse.rs+2-9| ... | ... | @@ -216,15 +216,8 @@ pub trait ProofTreeVisitor<'tcx> { |
| 216 | 216 | fn visit_goal(&mut self, goal: &InspectGoal<'_, 'tcx>) -> ControlFlow<Self::BreakTy>; |
| 217 | 217 | } |
| 218 | 218 | |
| 219 | pub trait ProofTreeInferCtxtExt<'tcx> { | |
| 220 | fn visit_proof_tree<V: ProofTreeVisitor<'tcx>>( | |
| 221 | &self, | |
| 222 | goal: Goal<'tcx, ty::Predicate<'tcx>>, | |
| 223 | visitor: &mut V, | |
| 224 | ) -> ControlFlow<V::BreakTy>; | |
| 225 | } | |
| 226 | ||
| 227 | impl<'tcx> ProofTreeInferCtxtExt<'tcx> for InferCtxt<'tcx> { | |
| 219 | #[extension(pub trait ProofTreeInferCtxtExt<'tcx>)] | |
| 220 | impl<'tcx> InferCtxt<'tcx> { | |
| 228 | 221 | fn visit_proof_tree<V: ProofTreeVisitor<'tcx>>( |
| 229 | 222 | &self, |
| 230 | 223 | goal: Goal<'tcx, ty::Predicate<'tcx>>, |
compiler/rustc_trait_selection/src/solve/mod.rs+2-5| ... | ... | @@ -61,11 +61,8 @@ enum GoalEvaluationKind { |
| 61 | 61 | Nested { is_normalizes_to_hack: IsNormalizesToHack }, |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | trait CanonicalResponseExt { | |
| 65 | fn has_no_inference_or_external_constraints(&self) -> bool; | |
| 66 | } | |
| 67 | ||
| 68 | impl<'tcx> CanonicalResponseExt for Canonical<'tcx, Response<'tcx>> { | |
| 64 | #[extension(trait CanonicalResponseExt)] | |
| 65 | impl<'tcx> Canonical<'tcx, Response<'tcx>> { | |
| 69 | 66 | fn has_no_inference_or_external_constraints(&self) -> bool { |
| 70 | 67 | self.value.external_constraints.region_constraints.is_empty() |
| 71 | 68 | && self.value.var_values.is_identity() |
compiler/rustc_trait_selection/src/traits/engine.rs+2-5| ... | ... | @@ -27,11 +27,8 @@ use rustc_middle::ty::TypeFoldable; |
| 27 | 27 | use rustc_middle::ty::Variance; |
| 28 | 28 | use rustc_middle::ty::{self, Ty, TyCtxt}; |
| 29 | 29 | |
| 30 | pub trait TraitEngineExt<'tcx> { | |
| 31 | fn new(infcx: &InferCtxt<'tcx>) -> Box<Self>; | |
| 32 | } | |
| 33 | ||
| 34 | impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> { | |
| 30 | #[extension(pub trait TraitEngineExt<'tcx>)] | |
| 31 | impl<'tcx> dyn TraitEngine<'tcx> { | |
| 35 | 32 | fn new(infcx: &InferCtxt<'tcx>) -> Box<Self> { |
| 36 | 33 | if infcx.next_trait_solver() { |
| 37 | 34 | Box::new(NextFulfillmentCtxt::new(infcx)) |
compiler/rustc_trait_selection/src/traits/error_reporting/infer_ctxt_ext.rs+5-32| ... | ... | @@ -11,38 +11,8 @@ use super::ArgKind; |
| 11 | 11 | |
| 12 | 12 | pub use rustc_infer::traits::error_reporting::*; |
| 13 | 13 | |
| 14 | pub trait InferCtxtExt<'tcx> { | |
| 15 | /// Given some node representing a fn-like thing in the HIR map, | |
| 16 | /// returns a span and `ArgKind` information that describes the | |
| 17 | /// arguments it expects. This can be supplied to | |
| 18 | /// `report_arg_count_mismatch`. | |
| 19 | fn get_fn_like_arguments(&self, node: Node<'_>) -> Option<(Span, Option<Span>, Vec<ArgKind>)>; | |
| 20 | ||
| 21 | /// Reports an error when the number of arguments needed by a | |
| 22 | /// trait match doesn't match the number that the expression | |
| 23 | /// provides. | |
| 24 | fn report_arg_count_mismatch( | |
| 25 | &self, | |
| 26 | span: Span, | |
| 27 | found_span: Option<Span>, | |
| 28 | expected_args: Vec<ArgKind>, | |
| 29 | found_args: Vec<ArgKind>, | |
| 30 | is_closure: bool, | |
| 31 | closure_pipe_span: Option<Span>, | |
| 32 | ) -> DiagnosticBuilder<'tcx>; | |
| 33 | ||
| 34 | /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce` | |
| 35 | /// in that order, and returns the generic type corresponding to the | |
| 36 | /// argument of that trait (corresponding to the closure arguments). | |
| 37 | fn type_implements_fn_trait( | |
| 38 | &self, | |
| 39 | param_env: ty::ParamEnv<'tcx>, | |
| 40 | ty: ty::Binder<'tcx, Ty<'tcx>>, | |
| 41 | polarity: ty::ImplPolarity, | |
| 42 | ) -> Result<(ty::ClosureKind, ty::Binder<'tcx, Ty<'tcx>>), ()>; | |
| 43 | } | |
| 44 | ||
| 45 | impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { | |
| 14 | #[extension(pub trait InferCtxtExt<'tcx>)] | |
| 15 | impl<'tcx> InferCtxt<'tcx> { | |
| 46 | 16 | /// Given some node representing a fn-like thing in the HIR map, |
| 47 | 17 | /// returns a span and `ArgKind` information that describes the |
| 48 | 18 | /// arguments it expects. This can be supplied to |
| ... | ... | @@ -229,6 +199,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { |
| 229 | 199 | err |
| 230 | 200 | } |
| 231 | 201 | |
| 202 | /// Checks if the type implements one of `Fn`, `FnMut`, or `FnOnce` | |
| 203 | /// in that order, and returns the generic type corresponding to the | |
| 204 | /// argument of that trait (corresponding to the closure arguments). | |
| 232 | 205 | fn type_implements_fn_trait( |
| 233 | 206 | &self, |
| 234 | 207 | param_env: ty::ParamEnv<'tcx>, |
compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs+2-19| ... | ... | @@ -23,24 +23,6 @@ use crate::errors::{ |
| 23 | 23 | |
| 24 | 24 | use crate::traits::error_reporting::type_err_ctxt_ext::InferCtxtPrivExt; |
| 25 | 25 | |
| 26 | pub trait TypeErrCtxtExt<'tcx> { | |
| 27 | /*private*/ | |
| 28 | fn impl_similar_to( | |
| 29 | &self, | |
| 30 | trait_ref: ty::PolyTraitRef<'tcx>, | |
| 31 | obligation: &PredicateObligation<'tcx>, | |
| 32 | ) -> Option<(DefId, GenericArgsRef<'tcx>)>; | |
| 33 | ||
| 34 | /*private*/ | |
| 35 | fn describe_enclosure(&self, def_id: LocalDefId) -> Option<&'static str>; | |
| 36 | ||
| 37 | fn on_unimplemented_note( | |
| 38 | &self, | |
| 39 | trait_ref: ty::PolyTraitRef<'tcx>, | |
| 40 | obligation: &PredicateObligation<'tcx>, | |
| 41 | ) -> OnUnimplementedNote; | |
| 42 | } | |
| 43 | ||
| 44 | 26 | /// The symbols which are always allowed in a format string |
| 45 | 27 | static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[ |
| 46 | 28 | kw::SelfUpper, |
| ... | ... | @@ -56,7 +38,8 @@ static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[ |
| 56 | 38 | sym::Trait, |
| 57 | 39 | ]; |
| 58 | 40 | |
| 59 | impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { | |
| 41 | #[extension(pub trait TypeErrCtxtExt<'tcx>)] | |
| 42 | impl<'tcx> TypeErrCtxt<'_, 'tcx> { | |
| 60 | 43 | fn impl_similar_to( |
| 61 | 44 | &self, |
| 62 | 45 | trait_ref: ty::PolyTraitRef<'tcx>, |
compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs+2-274| ... | ... | @@ -106,279 +106,6 @@ impl<'tcx, 'a> CoroutineData<'tcx, 'a> { |
| 106 | 106 | } |
| 107 | 107 | } |
| 108 | 108 | |
| 109 | // This trait is public to expose the diagnostics methods to clippy. | |
| 110 | pub trait TypeErrCtxtExt<'tcx> { | |
| 111 | fn suggest_restricting_param_bound( | |
| 112 | &self, | |
| 113 | err: &mut Diagnostic, | |
| 114 | trait_pred: ty::PolyTraitPredicate<'tcx>, | |
| 115 | associated_item: Option<(&'static str, Ty<'tcx>)>, | |
| 116 | body_id: LocalDefId, | |
| 117 | ); | |
| 118 | ||
| 119 | fn suggest_dereferences( | |
| 120 | &self, | |
| 121 | obligation: &PredicateObligation<'tcx>, | |
| 122 | err: &mut Diagnostic, | |
| 123 | trait_pred: ty::PolyTraitPredicate<'tcx>, | |
| 124 | ) -> bool; | |
| 125 | ||
| 126 | fn get_closure_name( | |
| 127 | &self, | |
| 128 | def_id: DefId, | |
| 129 | err: &mut Diagnostic, | |
| 130 | msg: Cow<'static, str>, | |
| 131 | ) -> Option<Symbol>; | |
| 132 | ||
| 133 | fn suggest_fn_call( | |
| 134 | &self, | |
| 135 | obligation: &PredicateObligation<'tcx>, | |
| 136 | err: &mut Diagnostic, | |
| 137 | trait_pred: ty::PolyTraitPredicate<'tcx>, | |
| 138 | ) -> bool; | |
| 139 | ||
| 140 | fn check_for_binding_assigned_block_without_tail_expression( | |
| 141 | &self, | |
| 142 | obligation: &PredicateObligation<'tcx>, | |
| 143 | err: &mut Diagnostic, | |
| 144 | trait_pred: ty::PolyTraitPredicate<'tcx>, | |
| 145 | ); | |
| 146 | ||
| 147 | fn suggest_add_clone_to_arg( | |
| 148 | &self, | |
| 149 | obligation: &PredicateObligation<'tcx>, | |
| 150 | err: &mut Diagnostic, | |
| 151 | trait_pred: ty::PolyTraitPredicate<'tcx>, | |
| 152 | ) -> bool; | |
| 153 | ||
| 154 | fn extract_callable_info( | |
| 155 | &self, | |
| 156 | body_id: LocalDefId, | |
| 157 | param_env: ty::ParamEnv<'tcx>, | |
| 158 | found: Ty<'tcx>, | |
| 159 | ) -> Option<(DefIdOrName, Ty<'tcx>, Vec<Ty<'tcx>>)>; | |
| 160 | ||
| 161 | fn suggest_add_reference_to_arg( | |
| 162 | &self, | |
| 163 | obligation: &PredicateObligation<'tcx>, | |
| 164 | err: &mut Diagnostic, | |
| 165 | trait_pred: ty::PolyTraitPredicate<'tcx>, | |
| 166 | has_custom_message: bool, | |
| 167 | ) -> bool; | |
| 168 | ||
| 169 | fn suggest_borrowing_for_object_cast( | |
| 170 | &self, | |
| 171 | err: &mut Diagnostic, | |
| 172 | obligation: &PredicateObligation<'tcx>, | |
| 173 | self_ty: Ty<'tcx>, | |
| 174 | object_ty: Ty<'tcx>, | |
| 175 | ); | |
| 176 | ||
| 177 | fn suggest_remove_reference( | |
| 178 | &self, | |
| 179 | obligation: &PredicateObligation<'tcx>, | |
| 180 | err: &mut Diagnostic, | |
| 181 | trait_pred: ty::PolyTraitPredicate<'tcx>, | |
| 182 | ) -> bool; | |
| 183 | ||
| 184 | fn suggest_remove_await(&self, obligation: &PredicateObligation<'tcx>, err: &mut Diagnostic); | |
| 185 | ||
| 186 | fn suggest_change_mut( | |
| 187 | &self, | |
| 188 | obligation: &PredicateObligation<'tcx>, | |
| 189 | err: &mut Diagnostic, | |
| 190 | trait_pred: ty::PolyTraitPredicate<'tcx>, | |
| 191 | ); | |
| 192 | ||
| 193 | fn suggest_semicolon_removal( | |
| 194 | &self, | |
| 195 | obligation: &PredicateObligation<'tcx>, | |
| 196 | err: &mut Diagnostic, | |
| 197 | span: Span, | |
| 198 | trait_pred: ty::PolyTraitPredicate<'tcx>, | |
| 199 | ) -> bool; | |
| 200 | ||
| 201 | fn return_type_span(&self, obligation: &PredicateObligation<'tcx>) -> Option<Span>; | |
| 202 | ||
| 203 | fn suggest_impl_trait( | |
| 204 | &self, | |
| 205 | err: &mut Diagnostic, | |
| 206 | obligation: &PredicateObligation<'tcx>, | |
| 207 | trait_pred: ty::PolyTraitPredicate<'tcx>, | |
| 208 | ) -> bool; | |
| 209 | ||
| 210 | fn point_at_returns_when_relevant( | |
| 211 | &self, | |
| 212 | err: &mut DiagnosticBuilder<'tcx>, | |
| 213 | obligation: &PredicateObligation<'tcx>, | |
| 214 | ); | |
| 215 | ||
| 216 | fn report_closure_arg_mismatch( | |
| 217 | &self, | |
| 218 | span: Span, | |
| 219 | found_span: Option<Span>, | |
| 220 | found: ty::PolyTraitRef<'tcx>, | |
| 221 | expected: ty::PolyTraitRef<'tcx>, | |
| 222 | cause: &ObligationCauseCode<'tcx>, | |
| 223 | found_node: Option<Node<'_>>, | |
| 224 | param_env: ty::ParamEnv<'tcx>, | |
| 225 | ) -> DiagnosticBuilder<'tcx>; | |
| 226 | ||
| 227 | fn note_conflicting_fn_args( | |
| 228 | &self, | |
| 229 | err: &mut Diagnostic, | |
| 230 | cause: &ObligationCauseCode<'tcx>, | |
| 231 | expected: Ty<'tcx>, | |
| 232 | found: Ty<'tcx>, | |
| 233 | param_env: ty::ParamEnv<'tcx>, | |
| 234 | ); | |
| 235 | ||
| 236 | fn note_conflicting_closure_bounds( | |
| 237 | &self, | |
| 238 | cause: &ObligationCauseCode<'tcx>, | |
| 239 | err: &mut DiagnosticBuilder<'tcx>, | |
| 240 | ); | |
| 241 | ||
| 242 | fn suggest_fully_qualified_path( | |
| 243 | &self, | |
| 244 | err: &mut Diagnostic, | |
| 245 | item_def_id: DefId, | |
| 246 | span: Span, | |
| 247 | trait_ref: DefId, | |
| 248 | ); | |
| 249 | ||
| 250 | fn maybe_note_obligation_cause_for_async_await( | |
| 251 | &self, | |
| 252 | err: &mut Diagnostic, | |
| 253 | obligation: &PredicateObligation<'tcx>, | |
| 254 | ) -> bool; | |
| 255 | ||
| 256 | fn note_obligation_cause_for_async_await( | |
| 257 | &self, | |
| 258 | err: &mut Diagnostic, | |
| 259 | interior_or_upvar_span: CoroutineInteriorOrUpvar, | |
| 260 | is_async: bool, | |
| 261 | outer_coroutine: Option<DefId>, | |
| 262 | trait_pred: ty::TraitPredicate<'tcx>, | |
| 263 | target_ty: Ty<'tcx>, | |
| 264 | obligation: &PredicateObligation<'tcx>, | |
| 265 | next_code: Option<&ObligationCauseCode<'tcx>>, | |
| 266 | ); | |
| 267 | ||
| 268 | fn note_obligation_cause_code<T>( | |
| 269 | &self, | |
| 270 | body_id: LocalDefId, | |
| 271 | err: &mut Diagnostic, | |
| 272 | predicate: T, | |
| 273 | param_env: ty::ParamEnv<'tcx>, | |
| 274 | cause_code: &ObligationCauseCode<'tcx>, | |
| 275 | obligated_types: &mut Vec<Ty<'tcx>>, | |
| 276 | seen_requirements: &mut FxHashSet<DefId>, | |
| 277 | ) where | |
| 278 | T: ToPredicate<'tcx>; | |
| 279 | ||
| 280 | /// Suggest to await before try: future? => future.await? | |
| 281 | fn suggest_await_before_try( | |
| 282 | &self, | |
| 283 | err: &mut Diagnostic, | |
| 284 | obligation: &PredicateObligation<'tcx>, | |
| 285 | trait_pred: ty::PolyTraitPredicate<'tcx>, | |
| 286 | span: Span, | |
| 287 | ); | |
| 288 | ||
| 289 | fn suggest_floating_point_literal( | |
| 290 | &self, | |
| 291 | obligation: &PredicateObligation<'tcx>, | |
| 292 | err: &mut Diagnostic, | |
| 293 | trait_ref: &ty::PolyTraitRef<'tcx>, | |
| 294 | ); | |
| 295 | ||
| 296 | fn suggest_derive( | |
| 297 | &self, | |
| 298 | obligation: &PredicateObligation<'tcx>, | |
| 299 | err: &mut Diagnostic, | |
| 300 | trait_pred: ty::PolyTraitPredicate<'tcx>, | |
| 301 | ); | |
| 302 | ||
| 303 | fn suggest_dereferencing_index( | |
| 304 | &self, | |
| 305 | obligation: &PredicateObligation<'tcx>, | |
| 306 | err: &mut Diagnostic, | |
| 307 | trait_pred: ty::PolyTraitPredicate<'tcx>, | |
| 308 | ); | |
| 309 | ||
| 310 | fn suggest_option_method_if_applicable( | |
| 311 | &self, | |
| 312 | failed_pred: ty::Predicate<'tcx>, | |
| 313 | param_env: ty::ParamEnv<'tcx>, | |
| 314 | err: &mut Diagnostic, | |
| 315 | expr: &hir::Expr<'_>, | |
| 316 | ); | |
| 317 | ||
| 318 | fn note_function_argument_obligation( | |
| 319 | &self, | |
| 320 | body_id: LocalDefId, | |
| 321 | err: &mut Diagnostic, | |
| 322 | arg_hir_id: HirId, | |
| 323 | parent_code: &ObligationCauseCode<'tcx>, | |
| 324 | param_env: ty::ParamEnv<'tcx>, | |
| 325 | predicate: ty::Predicate<'tcx>, | |
| 326 | call_hir_id: HirId, | |
| 327 | ); | |
| 328 | ||
| 329 | fn look_for_iterator_item_mistakes( | |
| 330 | &self, | |
| 331 | assocs_in_this_method: &[Option<(Span, (DefId, Ty<'tcx>))>], | |
| 332 | typeck_results: &TypeckResults<'tcx>, | |
| 333 | type_diffs: &[TypeError<'tcx>], | |
| 334 | param_env: ty::ParamEnv<'tcx>, | |
| 335 | path_segment: &hir::PathSegment<'_>, | |
| 336 | args: &[hir::Expr<'_>], | |
| 337 | err: &mut Diagnostic, | |
| 338 | ); | |
| 339 | ||
| 340 | fn point_at_chain( | |
| 341 | &self, | |
| 342 | expr: &hir::Expr<'_>, | |
| 343 | typeck_results: &TypeckResults<'tcx>, | |
| 344 | type_diffs: Vec<TypeError<'tcx>>, | |
| 345 | param_env: ty::ParamEnv<'tcx>, | |
| 346 | err: &mut Diagnostic, | |
| 347 | ); | |
| 348 | ||
| 349 | fn probe_assoc_types_at_expr( | |
| 350 | &self, | |
| 351 | type_diffs: &[TypeError<'tcx>], | |
| 352 | span: Span, | |
| 353 | prev_ty: Ty<'tcx>, | |
| 354 | body_id: hir::HirId, | |
| 355 | param_env: ty::ParamEnv<'tcx>, | |
| 356 | ) -> Vec<Option<(Span, (DefId, Ty<'tcx>))>>; | |
| 357 | ||
| 358 | fn suggest_convert_to_slice( | |
| 359 | &self, | |
| 360 | err: &mut Diagnostic, | |
| 361 | obligation: &PredicateObligation<'tcx>, | |
| 362 | trait_ref: ty::PolyTraitRef<'tcx>, | |
| 363 | candidate_impls: &[ImplCandidate<'tcx>], | |
| 364 | span: Span, | |
| 365 | ); | |
| 366 | ||
| 367 | fn explain_hrtb_projection( | |
| 368 | &self, | |
| 369 | diag: &mut Diagnostic, | |
| 370 | pred: ty::PolyTraitPredicate<'tcx>, | |
| 371 | param_env: ty::ParamEnv<'tcx>, | |
| 372 | cause: &ObligationCause<'tcx>, | |
| 373 | ); | |
| 374 | ||
| 375 | fn suggest_desugaring_async_fn_in_trait( | |
| 376 | &self, | |
| 377 | err: &mut Diagnostic, | |
| 378 | trait_ref: ty::PolyTraitRef<'tcx>, | |
| 379 | ); | |
| 380 | } | |
| 381 | ||
| 382 | 109 | fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) -> (Span, String) { |
| 383 | 110 | ( |
| 384 | 111 | generics.tail_span_for_predicate_suggestion(), |
| ... | ... | @@ -509,7 +236,8 @@ pub fn suggest_restriction<'tcx>( |
| 509 | 236 | } |
| 510 | 237 | } |
| 511 | 238 | |
| 512 | impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { | |
| 239 | #[extension(pub trait TypeErrCtxtExt<'tcx>)] | |
| 240 | impl<'tcx> TypeErrCtxt<'_, 'tcx> { | |
| 513 | 241 | fn suggest_restricting_param_bound( |
| 514 | 242 | &self, |
| 515 | 243 | err: &mut Diagnostic, |
compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs+11-275| ... | ... | @@ -57,78 +57,8 @@ use super::{ |
| 57 | 57 | |
| 58 | 58 | pub use rustc_infer::traits::error_reporting::*; |
| 59 | 59 | |
| 60 | pub trait TypeErrCtxtExt<'tcx> { | |
| 61 | fn build_overflow_error<T>( | |
| 62 | &self, | |
| 63 | predicate: &T, | |
| 64 | span: Span, | |
| 65 | suggest_increasing_limit: bool, | |
| 66 | ) -> DiagnosticBuilder<'tcx> | |
| 67 | where | |
| 68 | T: fmt::Display + TypeFoldable<TyCtxt<'tcx>> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>; | |
| 69 | ||
| 70 | fn report_overflow_error<T>( | |
| 71 | &self, | |
| 72 | predicate: &T, | |
| 73 | span: Span, | |
| 74 | suggest_increasing_limit: bool, | |
| 75 | mutate: impl FnOnce(&mut Diagnostic), | |
| 76 | ) -> ! | |
| 77 | where | |
| 78 | T: fmt::Display + TypeFoldable<TyCtxt<'tcx>> + Print<'tcx, FmtPrinter<'tcx, 'tcx>>; | |
| 79 | ||
| 80 | fn report_overflow_no_abort(&self, obligation: PredicateObligation<'tcx>) -> ErrorGuaranteed; | |
| 81 | ||
| 82 | fn report_fulfillment_errors(&self, errors: Vec<FulfillmentError<'tcx>>) -> ErrorGuaranteed; | |
| 83 | ||
| 84 | fn report_overflow_obligation<T>( | |
| 85 | &self, | |
| 86 | obligation: &Obligation<'tcx, T>, | |
| 87 | suggest_increasing_limit: bool, | |
| 88 | ) -> ! | |
| 89 | where | |
| 90 | T: ToPredicate<'tcx> + Clone; | |
| 91 | ||
| 92 | fn suggest_new_overflow_limit(&self, err: &mut Diagnostic); | |
| 93 | ||
| 94 | fn report_overflow_obligation_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !; | |
| 95 | ||
| 96 | /// The `root_obligation` parameter should be the `root_obligation` field | |
| 97 | /// from a `FulfillmentError`. If no `FulfillmentError` is available, | |
| 98 | /// then it should be the same as `obligation`. | |
| 99 | fn report_selection_error( | |
| 100 | &self, | |
| 101 | obligation: PredicateObligation<'tcx>, | |
| 102 | root_obligation: &PredicateObligation<'tcx>, | |
| 103 | error: &SelectionError<'tcx>, | |
| 104 | ) -> ErrorGuaranteed; | |
| 105 | ||
| 106 | fn emit_specialized_closure_kind_error( | |
| 107 | &self, | |
| 108 | obligation: &PredicateObligation<'tcx>, | |
| 109 | trait_ref: ty::PolyTraitRef<'tcx>, | |
| 110 | ) -> Option<ErrorGuaranteed>; | |
| 111 | ||
| 112 | fn fn_arg_obligation( | |
| 113 | &self, | |
| 114 | obligation: &PredicateObligation<'tcx>, | |
| 115 | ) -> Result<(), ErrorGuaranteed>; | |
| 116 | ||
| 117 | fn try_conversion_context( | |
| 118 | &self, | |
| 119 | obligation: &PredicateObligation<'tcx>, | |
| 120 | trait_ref: ty::TraitRef<'tcx>, | |
| 121 | err: &mut Diagnostic, | |
| 122 | ) -> bool; | |
| 123 | ||
| 124 | fn report_const_param_not_wf( | |
| 125 | &self, | |
| 126 | ty: Ty<'tcx>, | |
| 127 | obligation: &PredicateObligation<'tcx>, | |
| 128 | ) -> DiagnosticBuilder<'tcx>; | |
| 129 | } | |
| 130 | ||
| 131 | impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { | |
| 60 | #[extension(pub trait TypeErrCtxtExt<'tcx>)] | |
| 61 | impl<'tcx> TypeErrCtxt<'_, 'tcx> { | |
| 132 | 62 | fn report_fulfillment_errors( |
| 133 | 63 | &self, |
| 134 | 64 | mut errors: Vec<FulfillmentError<'tcx>>, |
| ... | ... | @@ -382,6 +312,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { |
| 382 | 312 | err.emit() |
| 383 | 313 | } |
| 384 | 314 | |
| 315 | /// The `root_obligation` parameter should be the `root_obligation` field | |
| 316 | /// from a `FulfillmentError`. If no `FulfillmentError` is available, | |
| 317 | /// then it should be the same as `obligation`. | |
| 385 | 318 | fn report_selection_error( |
| 386 | 319 | &self, |
| 387 | 320 | mut obligation: PredicateObligation<'tcx>, |
| ... | ... | @@ -1393,209 +1326,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { |
| 1393 | 1326 | } |
| 1394 | 1327 | } |
| 1395 | 1328 | |
| 1396 | pub(super) trait InferCtxtPrivExt<'tcx> { | |
| 1397 | // returns if `cond` not occurring implies that `error` does not occur - i.e., that | |
| 1398 | // `error` occurring implies that `cond` occurs. | |
| 1399 | fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool; | |
| 1400 | ||
| 1401 | fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>) -> ErrorGuaranteed; | |
| 1402 | ||
| 1403 | fn report_projection_error( | |
| 1404 | &self, | |
| 1405 | obligation: &PredicateObligation<'tcx>, | |
| 1406 | error: &MismatchedProjectionTypes<'tcx>, | |
| 1407 | ) -> ErrorGuaranteed; | |
| 1408 | ||
| 1409 | fn maybe_detailed_projection_msg( | |
| 1410 | &self, | |
| 1411 | pred: ty::ProjectionPredicate<'tcx>, | |
| 1412 | normalized_ty: ty::Term<'tcx>, | |
| 1413 | expected_ty: ty::Term<'tcx>, | |
| 1414 | ) -> Option<String>; | |
| 1415 | ||
| 1416 | fn fuzzy_match_tys( | |
| 1417 | &self, | |
| 1418 | a: Ty<'tcx>, | |
| 1419 | b: Ty<'tcx>, | |
| 1420 | ignoring_lifetimes: bool, | |
| 1421 | ) -> Option<CandidateSimilarity>; | |
| 1422 | ||
| 1423 | fn describe_closure(&self, kind: hir::ClosureKind) -> &'static str; | |
| 1424 | ||
| 1425 | fn find_similar_impl_candidates( | |
| 1426 | &self, | |
| 1427 | trait_pred: ty::PolyTraitPredicate<'tcx>, | |
| 1428 | ) -> Vec<ImplCandidate<'tcx>>; | |
| 1429 | ||
| 1430 | fn report_similar_impl_candidates( | |
| 1431 | &self, | |
| 1432 | impl_candidates: &[ImplCandidate<'tcx>], | |
| 1433 | trait_ref: ty::PolyTraitRef<'tcx>, | |
| 1434 | body_def_id: LocalDefId, | |
| 1435 | err: &mut Diagnostic, | |
| 1436 | other: bool, | |
| 1437 | param_env: ty::ParamEnv<'tcx>, | |
| 1438 | ) -> bool; | |
| 1439 | ||
| 1440 | fn report_similar_impl_candidates_for_root_obligation( | |
| 1441 | &self, | |
| 1442 | obligation: &PredicateObligation<'tcx>, | |
| 1443 | trait_predicate: ty::Binder<'tcx, ty::TraitPredicate<'tcx>>, | |
| 1444 | body_def_id: LocalDefId, | |
| 1445 | err: &mut Diagnostic, | |
| 1446 | ); | |
| 1447 | ||
| 1448 | /// Gets the parent trait chain start | |
| 1449 | fn get_parent_trait_ref( | |
| 1450 | &self, | |
| 1451 | code: &ObligationCauseCode<'tcx>, | |
| 1452 | ) -> Option<(Ty<'tcx>, Option<Span>)>; | |
| 1453 | ||
| 1454 | /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait | |
| 1455 | /// with the same path as `trait_ref`, a help message about | |
| 1456 | /// a probable version mismatch is added to `err` | |
| 1457 | fn note_version_mismatch( | |
| 1458 | &self, | |
| 1459 | err: &mut Diagnostic, | |
| 1460 | trait_ref: &ty::PolyTraitRef<'tcx>, | |
| 1461 | ) -> bool; | |
| 1462 | ||
| 1463 | /// Creates a `PredicateObligation` with `new_self_ty` replacing the existing type in the | |
| 1464 | /// `trait_ref`. | |
| 1465 | /// | |
| 1466 | /// For this to work, `new_self_ty` must have no escaping bound variables. | |
| 1467 | fn mk_trait_obligation_with_new_self_ty( | |
| 1468 | &self, | |
| 1469 | param_env: ty::ParamEnv<'tcx>, | |
| 1470 | trait_ref_and_ty: ty::Binder<'tcx, (ty::TraitPredicate<'tcx>, Ty<'tcx>)>, | |
| 1471 | ) -> PredicateObligation<'tcx>; | |
| 1472 | ||
| 1473 | fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) -> ErrorGuaranteed; | |
| 1474 | ||
| 1475 | fn predicate_can_apply( | |
| 1476 | &self, | |
| 1477 | param_env: ty::ParamEnv<'tcx>, | |
| 1478 | pred: ty::PolyTraitPredicate<'tcx>, | |
| 1479 | ) -> bool; | |
| 1480 | ||
| 1481 | fn note_obligation_cause(&self, err: &mut Diagnostic, obligation: &PredicateObligation<'tcx>); | |
| 1482 | ||
| 1483 | fn suggest_unsized_bound_if_applicable( | |
| 1484 | &self, | |
| 1485 | err: &mut Diagnostic, | |
| 1486 | obligation: &PredicateObligation<'tcx>, | |
| 1487 | ); | |
| 1488 | ||
| 1489 | fn annotate_source_of_ambiguity( | |
| 1490 | &self, | |
| 1491 | err: &mut Diagnostic, | |
| 1492 | impls: &[ambiguity::Ambiguity], | |
| 1493 | predicate: ty::Predicate<'tcx>, | |
| 1494 | ); | |
| 1495 | ||
| 1496 | fn maybe_suggest_unsized_generics(&self, err: &mut Diagnostic, span: Span, node: Node<'tcx>); | |
| 1497 | ||
| 1498 | fn maybe_indirection_for_unsized( | |
| 1499 | &self, | |
| 1500 | err: &mut Diagnostic, | |
| 1501 | item: &'tcx Item<'tcx>, | |
| 1502 | param: &'tcx GenericParam<'tcx>, | |
| 1503 | ) -> bool; | |
| 1504 | ||
| 1505 | fn is_recursive_obligation( | |
| 1506 | &self, | |
| 1507 | obligated_types: &mut Vec<Ty<'tcx>>, | |
| 1508 | cause_code: &ObligationCauseCode<'tcx>, | |
| 1509 | ) -> bool; | |
| 1510 | ||
| 1511 | fn get_standard_error_message( | |
| 1512 | &self, | |
| 1513 | trait_predicate: &ty::PolyTraitPredicate<'tcx>, | |
| 1514 | message: Option<String>, | |
| 1515 | predicate_is_const: bool, | |
| 1516 | append_const_msg: Option<AppendConstMessage>, | |
| 1517 | post_message: String, | |
| 1518 | ) -> String; | |
| 1519 | ||
| 1520 | fn get_safe_transmute_error_and_reason( | |
| 1521 | &self, | |
| 1522 | obligation: PredicateObligation<'tcx>, | |
| 1523 | trait_ref: ty::PolyTraitRef<'tcx>, | |
| 1524 | span: Span, | |
| 1525 | ) -> GetSafeTransmuteErrorAndReason; | |
| 1526 | ||
| 1527 | fn add_tuple_trait_message( | |
| 1528 | &self, | |
| 1529 | obligation_cause_code: &ObligationCauseCode<'tcx>, | |
| 1530 | err: &mut Diagnostic, | |
| 1531 | ); | |
| 1532 | ||
| 1533 | fn try_to_add_help_message( | |
| 1534 | &self, | |
| 1535 | obligation: &PredicateObligation<'tcx>, | |
| 1536 | trait_ref: ty::PolyTraitRef<'tcx>, | |
| 1537 | trait_predicate: &ty::PolyTraitPredicate<'tcx>, | |
| 1538 | err: &mut Diagnostic, | |
| 1539 | span: Span, | |
| 1540 | is_fn_trait: bool, | |
| 1541 | suggested: bool, | |
| 1542 | unsatisfied_const: bool, | |
| 1543 | ); | |
| 1544 | ||
| 1545 | fn add_help_message_for_fn_trait( | |
| 1546 | &self, | |
| 1547 | trait_ref: ty::PolyTraitRef<'tcx>, | |
| 1548 | err: &mut Diagnostic, | |
| 1549 | implemented_kind: ty::ClosureKind, | |
| 1550 | params: ty::Binder<'tcx, Ty<'tcx>>, | |
| 1551 | ); | |
| 1552 | ||
| 1553 | fn maybe_add_note_for_unsatisfied_const( | |
| 1554 | &self, | |
| 1555 | trait_predicate: &ty::PolyTraitPredicate<'tcx>, | |
| 1556 | err: &mut Diagnostic, | |
| 1557 | span: Span, | |
| 1558 | ) -> UnsatisfiedConst; | |
| 1559 | ||
| 1560 | fn report_closure_error( | |
| 1561 | &self, | |
| 1562 | obligation: &PredicateObligation<'tcx>, | |
| 1563 | closure_def_id: DefId, | |
| 1564 | found_kind: ty::ClosureKind, | |
| 1565 | kind: ty::ClosureKind, | |
| 1566 | trait_prefix: &'static str, | |
| 1567 | ) -> DiagnosticBuilder<'tcx>; | |
| 1568 | ||
| 1569 | fn report_cyclic_signature_error( | |
| 1570 | &self, | |
| 1571 | obligation: &PredicateObligation<'tcx>, | |
| 1572 | found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, | |
| 1573 | expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, | |
| 1574 | terr: TypeError<'tcx>, | |
| 1575 | ) -> DiagnosticBuilder<'tcx>; | |
| 1576 | ||
| 1577 | fn report_opaque_type_auto_trait_leakage( | |
| 1578 | &self, | |
| 1579 | obligation: &PredicateObligation<'tcx>, | |
| 1580 | def_id: DefId, | |
| 1581 | ) -> DiagnosticBuilder<'tcx>; | |
| 1582 | ||
| 1583 | fn report_signature_mismatch_error( | |
| 1584 | &self, | |
| 1585 | obligation: &PredicateObligation<'tcx>, | |
| 1586 | span: Span, | |
| 1587 | found_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, | |
| 1588 | expected_trait_ref: ty::Binder<'tcx, ty::TraitRef<'tcx>>, | |
| 1589 | ) -> Result<DiagnosticBuilder<'tcx>, ErrorGuaranteed>; | |
| 1590 | ||
| 1591 | fn report_not_const_evaluatable_error( | |
| 1592 | &self, | |
| 1593 | obligation: &PredicateObligation<'tcx>, | |
| 1594 | span: Span, | |
| 1595 | ) -> Result<DiagnosticBuilder<'tcx>, ErrorGuaranteed>; | |
| 1596 | } | |
| 1597 | ||
| 1598 | impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { | |
| 1329 | #[extension(pub(super) trait InferCtxtPrivExt<'tcx>)] | |
| 1330 | impl<'tcx> TypeErrCtxt<'_, 'tcx> { | |
| 1599 | 1331 | // returns if `cond` not occurring implies that `error` does not occur - i.e., that |
| 1600 | 1332 | // `error` occurring implies that `cond` occurs. |
| 1601 | 1333 | fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool { |
| ... | ... | @@ -2414,6 +2146,10 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { |
| 2414 | 2146 | suggested |
| 2415 | 2147 | } |
| 2416 | 2148 | |
| 2149 | /// Creates a `PredicateObligation` with `new_self_ty` replacing the existing type in the | |
| 2150 | /// `trait_ref`. | |
| 2151 | /// | |
| 2152 | /// For this to work, `new_self_ty` must have no escaping bound variables. | |
| 2417 | 2153 | fn mk_trait_obligation_with_new_self_ty( |
| 2418 | 2154 | &self, |
| 2419 | 2155 | param_env: ty::ParamEnv<'tcx>, |
compiler/rustc_trait_selection/src/traits/outlives_bounds.rs+5-20| ... | ... | @@ -11,25 +11,6 @@ pub use rustc_middle::traits::query::OutlivesBound; |
| 11 | 11 | |
| 12 | 12 | pub type BoundsCompat<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a; |
| 13 | 13 | pub type Bounds<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a; |
| 14 | pub trait InferCtxtExt<'a, 'tcx> { | |
| 15 | /// Do *NOT* call this directly. | |
| 16 | fn implied_bounds_tys_compat( | |
| 17 | &'a self, | |
| 18 | param_env: ty::ParamEnv<'tcx>, | |
| 19 | body_id: LocalDefId, | |
| 20 | tys: &'a FxIndexSet<Ty<'tcx>>, | |
| 21 | compat: bool, | |
| 22 | ) -> BoundsCompat<'a, 'tcx>; | |
| 23 | ||
| 24 | /// If `-Z no-implied-bounds-compat` is set, calls `implied_bounds_tys_compat` | |
| 25 | /// with `compat` set to `true`, otherwise `false`. | |
| 26 | fn implied_bounds_tys( | |
| 27 | &'a self, | |
| 28 | param_env: ty::ParamEnv<'tcx>, | |
| 29 | body_id: LocalDefId, | |
| 30 | tys: &'a FxIndexSet<Ty<'tcx>>, | |
| 31 | ) -> Bounds<'a, 'tcx>; | |
| 32 | } | |
| 33 | 14 | |
| 34 | 15 | /// Implied bounds are region relationships that we deduce |
| 35 | 16 | /// automatically. The idea is that (e.g.) a caller must check that a |
| ... | ... | @@ -130,7 +111,9 @@ fn implied_outlives_bounds<'a, 'tcx>( |
| 130 | 111 | bounds |
| 131 | 112 | } |
| 132 | 113 | |
| 133 | impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { | |
| 114 | #[extension(pub trait InferCtxtExt<'a, 'tcx>)] | |
| 115 | impl<'a, 'tcx: 'a> InferCtxt<'tcx> { | |
| 116 | /// Do *NOT* call this directly. | |
| 134 | 117 | fn implied_bounds_tys_compat( |
| 135 | 118 | &'a self, |
| 136 | 119 | param_env: ParamEnv<'tcx>, |
| ... | ... | @@ -142,6 +125,8 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> { |
| 142 | 125 | .flat_map(move |ty| implied_outlives_bounds(self, param_env, body_id, *ty, compat)) |
| 143 | 126 | } |
| 144 | 127 | |
| 128 | /// If `-Z no-implied-bounds-compat` is set, calls `implied_bounds_tys_compat` | |
| 129 | /// with `compat` set to `true`, otherwise `false`. | |
| 145 | 130 | fn implied_bounds_tys( |
| 146 | 131 | &'a self, |
| 147 | 132 | param_env: ParamEnv<'tcx>, |
compiler/rustc_trait_selection/src/traits/project.rs+12-21| ... | ... | @@ -52,12 +52,22 @@ pub type ProjectionTyObligation<'tcx> = Obligation<'tcx, ty::AliasTy<'tcx>>; |
| 52 | 52 | |
| 53 | 53 | pub(super) struct InProgress; |
| 54 | 54 | |
| 55 | pub trait NormalizeExt<'tcx> { | |
| 55 | #[extension(pub trait NormalizeExt<'tcx>)] | |
| 56 | impl<'tcx> At<'_, 'tcx> { | |
| 56 | 57 | /// Normalize a value using the `AssocTypeNormalizer`. |
| 57 | 58 | /// |
| 58 | 59 | /// This normalization should be used when the type contains inference variables or the |
| 59 | 60 | /// projection may be fallible. |
| 60 | fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, t: T) -> InferOk<'tcx, T>; | |
| 61 | fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, value: T) -> InferOk<'tcx, T> { | |
| 62 | if self.infcx.next_trait_solver() { | |
| 63 | InferOk { value, obligations: Vec::new() } | |
| 64 | } else { | |
| 65 | let mut selcx = SelectionContext::new(self.infcx); | |
| 66 | let Normalized { value, obligations } = | |
| 67 | normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value); | |
| 68 | InferOk { value, obligations } | |
| 69 | } | |
| 70 | } | |
| 61 | 71 | |
| 62 | 72 | /// Deeply normalizes `value`, replacing all aliases which can by normalized in |
| 63 | 73 | /// the current environment. In the new solver this errors in case normalization |
| ... | ... | @@ -73,25 +83,6 @@ pub trait NormalizeExt<'tcx> { |
| 73 | 83 | /// existing fulfillment context in the old solver. Once we also eagerly prove goals with |
| 74 | 84 | /// the old solver or have removed the old solver, remove `traits::fully_normalize` and |
| 75 | 85 | /// rename this function to `At::fully_normalize`. |
| 76 | fn deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>( | |
| 77 | self, | |
| 78 | value: T, | |
| 79 | fulfill_cx: &mut dyn TraitEngine<'tcx>, | |
| 80 | ) -> Result<T, Vec<FulfillmentError<'tcx>>>; | |
| 81 | } | |
| 82 | ||
| 83 | impl<'tcx> NormalizeExt<'tcx> for At<'_, 'tcx> { | |
| 84 | fn normalize<T: TypeFoldable<TyCtxt<'tcx>>>(&self, value: T) -> InferOk<'tcx, T> { | |
| 85 | if self.infcx.next_trait_solver() { | |
| 86 | InferOk { value, obligations: Vec::new() } | |
| 87 | } else { | |
| 88 | let mut selcx = SelectionContext::new(self.infcx); | |
| 89 | let Normalized { value, obligations } = | |
| 90 | normalize_with_depth(&mut selcx, self.param_env, self.cause.clone(), 0, value); | |
| 91 | InferOk { value, obligations } | |
| 92 | } | |
| 93 | } | |
| 94 | ||
| 95 | 86 | fn deeply_normalize<T: TypeFoldable<TyCtxt<'tcx>>>( |
| 96 | 87 | self, |
| 97 | 88 | value: T, |
compiler/rustc_trait_selection/src/traits/query/evaluate_obligation.rs+5-29| ... | ... | @@ -4,32 +4,8 @@ use crate::infer::canonical::OriginalQueryValues; |
| 4 | 4 | use crate::infer::InferCtxt; |
| 5 | 5 | use crate::traits::{EvaluationResult, OverflowError, PredicateObligation, SelectionContext}; |
| 6 | 6 | |
| 7 | pub trait InferCtxtExt<'tcx> { | |
| 8 | fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool; | |
| 9 | ||
| 10 | fn predicate_must_hold_considering_regions( | |
| 11 | &self, | |
| 12 | obligation: &PredicateObligation<'tcx>, | |
| 13 | ) -> bool; | |
| 14 | ||
| 15 | fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool; | |
| 16 | ||
| 17 | fn evaluate_obligation( | |
| 18 | &self, | |
| 19 | obligation: &PredicateObligation<'tcx>, | |
| 20 | ) -> Result<EvaluationResult, OverflowError>; | |
| 21 | ||
| 22 | // Helper function that canonicalizes and runs the query. If an | |
| 23 | // overflow results, we re-run it in the local context so we can | |
| 24 | // report a nice error. | |
| 25 | /*crate*/ | |
| 26 | fn evaluate_obligation_no_overflow( | |
| 27 | &self, | |
| 28 | obligation: &PredicateObligation<'tcx>, | |
| 29 | ) -> EvaluationResult; | |
| 30 | } | |
| 31 | ||
| 32 | impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { | |
| 7 | #[extension(pub trait InferCtxtExt<'tcx>)] | |
| 8 | impl<'tcx> InferCtxt<'tcx> { | |
| 33 | 9 | /// Evaluates whether the predicate can be satisfied (by any means) |
| 34 | 10 | /// in the given `ParamEnv`. |
| 35 | 11 | fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool { |
| ... | ... | @@ -114,9 +90,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { |
| 114 | 90 | } |
| 115 | 91 | } |
| 116 | 92 | |
| 117 | // Helper function that canonicalizes and runs the query. If an | |
| 118 | // overflow results, we re-run it in the local context so we can | |
| 119 | // report a nice error. | |
| 93 | /// Helper function that canonicalizes and runs the query. If an | |
| 94 | /// overflow results, we re-run it in the local context so we can | |
| 95 | /// report a nice error. | |
| 120 | 96 | fn evaluate_obligation_no_overflow( |
| 121 | 97 | &self, |
| 122 | 98 | obligation: &PredicateObligation<'tcx>, |
compiler/rustc_trait_selection/src/traits/query/normalize.rs+8-14| ... | ... | @@ -22,20 +22,8 @@ use super::NoSolution; |
| 22 | 22 | |
| 23 | 23 | pub use rustc_middle::traits::query::NormalizationResult; |
| 24 | 24 | |
| 25 | pub trait QueryNormalizeExt<'tcx> { | |
| 26 | /// Normalize a value using the `QueryNormalizer`. | |
| 27 | /// | |
| 28 | /// This normalization should *only* be used when the projection does not | |
| 29 | /// have possible ambiguity or may not be well-formed. | |
| 30 | /// | |
| 31 | /// After codegen, when lifetimes do not matter, it is preferable to instead | |
| 32 | /// use [`TyCtxt::normalize_erasing_regions`], which wraps this procedure. | |
| 33 | fn query_normalize<T>(self, value: T) -> Result<Normalized<'tcx, T>, NoSolution> | |
| 34 | where | |
| 35 | T: TypeFoldable<TyCtxt<'tcx>>; | |
| 36 | } | |
| 37 | ||
| 38 | impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> { | |
| 25 | #[extension(pub trait QueryNormalizeExt<'tcx>)] | |
| 26 | impl<'cx, 'tcx> At<'cx, 'tcx> { | |
| 39 | 27 | /// Normalize `value` in the context of the inference context, |
| 40 | 28 | /// yielding a resulting type, or an error if `value` cannot be |
| 41 | 29 | /// normalized. If you don't care about regions, you should prefer |
| ... | ... | @@ -49,6 +37,12 @@ impl<'cx, 'tcx> QueryNormalizeExt<'tcx> for At<'cx, 'tcx> { |
| 49 | 37 | /// normalizing, but for now should be used only when we actually |
| 50 | 38 | /// know that normalization will succeed, since error reporting |
| 51 | 39 | /// and other details are still "under development". |
| 40 | /// | |
| 41 | /// This normalization should *only* be used when the projection does not | |
| 42 | /// have possible ambiguity or may not be well-formed. | |
| 43 | /// | |
| 44 | /// After codegen, when lifetimes do not matter, it is preferable to instead | |
| 45 | /// use [`TyCtxt::normalize_erasing_regions`], which wraps this procedure. | |
| 52 | 46 | fn query_normalize<T>(self, value: T) -> Result<Normalized<'tcx, T>, NoSolution> |
| 53 | 47 | where |
| 54 | 48 | T: TypeFoldable<TyCtxt<'tcx>>, |
compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs+4-30| ... | ... | @@ -33,20 +33,8 @@ enum Inserted<'tcx> { |
| 33 | 33 | ShouldRecurseOn(DefId), |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | trait ChildrenExt<'tcx> { | |
| 37 | fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId); | |
| 38 | fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId); | |
| 39 | ||
| 40 | fn insert( | |
| 41 | &mut self, | |
| 42 | tcx: TyCtxt<'tcx>, | |
| 43 | impl_def_id: DefId, | |
| 44 | simplified_self: Option<SimplifiedType>, | |
| 45 | overlap_mode: OverlapMode, | |
| 46 | ) -> Result<Inserted<'tcx>, OverlapError<'tcx>>; | |
| 47 | } | |
| 48 | ||
| 49 | impl<'tcx> ChildrenExt<'tcx> for Children { | |
| 36 | #[extension(trait ChildrenExt<'tcx>)] | |
| 37 | impl<'tcx> Children { | |
| 50 | 38 | /// Insert an impl into this set of children without comparing to any existing impls. |
| 51 | 39 | fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { |
| 52 | 40 | let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder(); |
| ... | ... | @@ -247,22 +235,8 @@ where |
| 247 | 235 | } |
| 248 | 236 | } |
| 249 | 237 | |
| 250 | pub trait GraphExt<'tcx> { | |
| 251 | /// Insert a local impl into the specialization graph. If an existing impl | |
| 252 | /// conflicts with it (has overlap, but neither specializes the other), | |
| 253 | /// information about the area of overlap is returned in the `Err`. | |
| 254 | fn insert( | |
| 255 | &mut self, | |
| 256 | tcx: TyCtxt<'tcx>, | |
| 257 | impl_def_id: DefId, | |
| 258 | overlap_mode: OverlapMode, | |
| 259 | ) -> Result<Option<FutureCompatOverlapError<'tcx>>, OverlapError<'tcx>>; | |
| 260 | ||
| 261 | /// Insert cached metadata mapping from a child impl back to its parent. | |
| 262 | fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'tcx>, parent: DefId, child: DefId); | |
| 263 | } | |
| 264 | ||
| 265 | impl<'tcx> GraphExt<'tcx> for Graph { | |
| 238 | #[extension(pub trait GraphExt<'tcx>)] | |
| 239 | impl<'tcx> Graph { | |
| 266 | 240 | /// Insert a local impl into the specialization graph. If an existing impl |
| 267 | 241 | /// conflicts with it (has overlap, but neither specializes the other), |
| 268 | 242 | /// information about the area of overlap is returned in the `Err`. |
compiler/rustc_trait_selection/src/traits/structural_normalize.rs+2-9| ... | ... | @@ -5,15 +5,8 @@ use rustc_middle::ty::{self, Ty}; |
| 5 | 5 | |
| 6 | 6 | use crate::traits::{NormalizeExt, Obligation}; |
| 7 | 7 | |
| 8 | pub trait StructurallyNormalizeExt<'tcx> { | |
| 9 | fn structurally_normalize( | |
| 10 | &self, | |
| 11 | ty: Ty<'tcx>, | |
| 12 | fulfill_cx: &mut dyn TraitEngine<'tcx>, | |
| 13 | ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>>; | |
| 14 | } | |
| 15 | ||
| 16 | impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> { | |
| 8 | #[extension(pub trait StructurallyNormalizeExt<'tcx>)] | |
| 9 | impl<'tcx> At<'_, 'tcx> { | |
| 17 | 10 | fn structurally_normalize( |
| 18 | 11 | &self, |
| 19 | 12 | ty: Ty<'tcx>, |
configure+2-2| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | #!/bin/sh |
| 2 | 2 | |
| 3 | script="$(dirname $0)"/src/bootstrap/configure.py | |
| 3 | script="$(dirname "$0")"/src/bootstrap/configure.py | |
| 4 | 4 | |
| 5 | 5 | try() { |
| 6 | 6 | cmd=$1 |
| ... | ... | @@ -15,4 +15,4 @@ try python3 "$@" |
| 15 | 15 | try python2.7 "$@" |
| 16 | 16 | try python27 "$@" |
| 17 | 17 | try python2 "$@" |
| 18 | exec python $script "$@" | |
| 18 | exec python "$script" "$@" |
library/core/src/intrinsics.rs+59-43| ... | ... | @@ -937,52 +937,68 @@ extern "rust-intrinsic" { |
| 937 | 937 | #[rustc_nounwind] |
| 938 | 938 | pub fn unreachable() -> !; |
| 939 | 939 | |
| 940 | /// Informs the optimizer that a condition is always true. | |
| 941 | /// If the condition is false, the behavior is undefined. | |
| 942 | /// | |
| 943 | /// No code is generated for this intrinsic, but the optimizer will try | |
| 944 | /// to preserve it (and its condition) between passes, which may interfere | |
| 945 | /// with optimization of surrounding code and reduce performance. It should | |
| 946 | /// not be used if the invariant can be discovered by the optimizer on its | |
| 947 | /// own, or if it does not enable any significant optimizations. | |
| 948 | /// | |
| 949 | /// This intrinsic does not have a stable counterpart. | |
| 950 | #[rustc_const_stable(feature = "const_assume", since = "1.77.0")] | |
| 951 | #[rustc_nounwind] | |
| 952 | pub fn assume(b: bool); | |
| 940 | } | |
| 953 | 941 | |
| 954 | /// Hints to the compiler that branch condition is likely to be true. | |
| 955 | /// Returns the value passed to it. | |
| 956 | /// | |
| 957 | /// Any use other than with `if` statements will probably not have an effect. | |
| 958 | /// | |
| 959 | /// Note that, unlike most intrinsics, this is safe to call; | |
| 960 | /// it does not require an `unsafe` block. | |
| 961 | /// Therefore, implementations must not require the user to uphold | |
| 962 | /// any safety invariants. | |
| 963 | /// | |
| 964 | /// This intrinsic does not have a stable counterpart. | |
| 965 | #[rustc_const_unstable(feature = "const_likely", issue = "none")] | |
| 966 | #[rustc_safe_intrinsic] | |
| 967 | #[rustc_nounwind] | |
| 968 | pub fn likely(b: bool) -> bool; | |
| 942 | /// Informs the optimizer that a condition is always true. | |
| 943 | /// If the condition is false, the behavior is undefined. | |
| 944 | /// | |
| 945 | /// No code is generated for this intrinsic, but the optimizer will try | |
| 946 | /// to preserve it (and its condition) between passes, which may interfere | |
| 947 | /// with optimization of surrounding code and reduce performance. It should | |
| 948 | /// not be used if the invariant can be discovered by the optimizer on its | |
| 949 | /// own, or if it does not enable any significant optimizations. | |
| 950 | /// | |
| 951 | /// This intrinsic does not have a stable counterpart. | |
| 952 | #[rustc_const_stable(feature = "const_assume", since = "1.77.0")] | |
| 953 | #[rustc_nounwind] | |
| 954 | #[unstable(feature = "core_intrinsics", issue = "none")] | |
| 955 | #[cfg_attr(not(bootstrap), rustc_intrinsic)] | |
| 956 | pub const unsafe fn assume(b: bool) { | |
| 957 | if !b { | |
| 958 | // SAFETY: the caller must guarantee the argument is never `false` | |
| 959 | unsafe { unreachable() } | |
| 960 | } | |
| 961 | } | |
| 969 | 962 | |
| 970 | /// Hints to the compiler that branch condition is likely to be false. | |
| 971 | /// Returns the value passed to it. | |
| 972 | /// | |
| 973 | /// Any use other than with `if` statements will probably not have an effect. | |
| 974 | /// | |
| 975 | /// Note that, unlike most intrinsics, this is safe to call; | |
| 976 | /// it does not require an `unsafe` block. | |
| 977 | /// Therefore, implementations must not require the user to uphold | |
| 978 | /// any safety invariants. | |
| 979 | /// | |
| 980 | /// This intrinsic does not have a stable counterpart. | |
| 981 | #[rustc_const_unstable(feature = "const_likely", issue = "none")] | |
| 982 | #[rustc_safe_intrinsic] | |
| 983 | #[rustc_nounwind] | |
| 984 | pub fn unlikely(b: bool) -> bool; | |
| 963 | /// Hints to the compiler that branch condition is likely to be true. | |
| 964 | /// Returns the value passed to it. | |
| 965 | /// | |
| 966 | /// Any use other than with `if` statements will probably not have an effect. | |
| 967 | /// | |
| 968 | /// Note that, unlike most intrinsics, this is safe to call; | |
| 969 | /// it does not require an `unsafe` block. | |
| 970 | /// Therefore, implementations must not require the user to uphold | |
| 971 | /// any safety invariants. | |
| 972 | /// | |
| 973 | /// This intrinsic does not have a stable counterpart. | |
| 974 | #[rustc_const_unstable(feature = "const_likely", issue = "none")] | |
| 975 | #[unstable(feature = "core_intrinsics", issue = "none")] | |
| 976 | #[cfg_attr(not(bootstrap), rustc_intrinsic)] | |
| 977 | #[rustc_nounwind] | |
| 978 | pub const fn likely(b: bool) -> bool { | |
| 979 | b | |
| 980 | } | |
| 981 | ||
| 982 | /// Hints to the compiler that branch condition is likely to be false. | |
| 983 | /// Returns the value passed to it. | |
| 984 | /// | |
| 985 | /// Any use other than with `if` statements will probably not have an effect. | |
| 986 | /// | |
| 987 | /// Note that, unlike most intrinsics, this is safe to call; | |
| 988 | /// it does not require an `unsafe` block. | |
| 989 | /// Therefore, implementations must not require the user to uphold | |
| 990 | /// any safety invariants. | |
| 991 | /// | |
| 992 | /// This intrinsic does not have a stable counterpart. | |
| 993 | #[rustc_const_unstable(feature = "const_likely", issue = "none")] | |
| 994 | #[unstable(feature = "core_intrinsics", issue = "none")] | |
| 995 | #[cfg_attr(not(bootstrap), rustc_intrinsic)] | |
| 996 | #[rustc_nounwind] | |
| 997 | pub const fn unlikely(b: bool) -> bool { | |
| 998 | b | |
| 999 | } | |
| 985 | 1000 | |
| 1001 | extern "rust-intrinsic" { | |
| 986 | 1002 | /// Executes a breakpoint trap, for inspection by a debugger. |
| 987 | 1003 | /// |
| 988 | 1004 | /// This intrinsic does not have a stable counterpart. |
library/core/src/slice/mod.rs+21-6| ... | ... | @@ -3016,8 +3016,13 @@ impl<T> [T] { |
| 3016 | 3016 | /// ``` |
| 3017 | 3017 | /// let mut v = [-5i32, 4, 2, -3, 1]; |
| 3018 | 3018 | /// |
| 3019 | /// // Find the median | |
| 3020 | /// v.select_nth_unstable(2); | |
| 3019 | /// // Find the items less than or equal to the median, the median, and greater than or equal to | |
| 3020 | /// // the median. | |
| 3021 | /// let (lesser, median, greater) = v.select_nth_unstable(2); | |
| 3022 | /// | |
| 3023 | /// assert!(lesser == [-3, -5] || lesser == [-5, -3]); | |
| 3024 | /// assert_eq!(median, &mut 1); | |
| 3025 | /// assert!(greater == [4, 2] || greater == [2, 4]); | |
| 3021 | 3026 | /// |
| 3022 | 3027 | /// // We are only guaranteed the slice will be one of the following, based on the way we sort |
| 3023 | 3028 | /// // about the specified index. |
| ... | ... | @@ -3067,8 +3072,13 @@ impl<T> [T] { |
| 3067 | 3072 | /// ``` |
| 3068 | 3073 | /// let mut v = [-5i32, 4, 2, -3, 1]; |
| 3069 | 3074 | /// |
| 3070 | /// // Find the median as if the slice were sorted in descending order. | |
| 3071 | /// v.select_nth_unstable_by(2, |a, b| b.cmp(a)); | |
| 3075 | /// // Find the items less than or equal to the median, the median, and greater than or equal to | |
| 3076 | /// // the median as if the slice were sorted in descending order. | |
| 3077 | /// let (lesser, median, greater) = v.select_nth_unstable_by(2, |a, b| b.cmp(a)); | |
| 3078 | /// | |
| 3079 | /// assert!(lesser == [4, 2] || lesser == [2, 4]); | |
| 3080 | /// assert_eq!(median, &mut 1); | |
| 3081 | /// assert!(greater == [-3, -5] || greater == [-5, -3]); | |
| 3072 | 3082 | /// |
| 3073 | 3083 | /// // We are only guaranteed the slice will be one of the following, based on the way we sort |
| 3074 | 3084 | /// // about the specified index. |
| ... | ... | @@ -3122,8 +3132,13 @@ impl<T> [T] { |
| 3122 | 3132 | /// ``` |
| 3123 | 3133 | /// let mut v = [-5i32, 4, 1, -3, 2]; |
| 3124 | 3134 | /// |
| 3125 | /// // Return the median as if the array were sorted according to absolute value. | |
| 3126 | /// v.select_nth_unstable_by_key(2, |a| a.abs()); | |
| 3135 | /// // Find the items less than or equal to the median, the median, and greater than or equal to | |
| 3136 | /// // the median as if the slice were sorted according to absolute value. | |
| 3137 | /// let (lesser, median, greater) = v.select_nth_unstable_by_key(2, |a| a.abs()); | |
| 3138 | /// | |
| 3139 | /// assert!(lesser == [1, 2] || lesser == [2, 1]); | |
| 3140 | /// assert_eq!(median, &mut -3); | |
| 3141 | /// assert!(greater == [4, -5] || greater == [-5, 4]); | |
| 3127 | 3142 | /// |
| 3128 | 3143 | /// // We are only guaranteed the slice will be one of the following, based on the way we sort |
| 3129 | 3144 | /// // about the specified index. |
library/std/src/sys/pal/windows/os.rs+25-5| ... | ... | @@ -318,13 +318,33 @@ pub fn temp_dir() -> PathBuf { |
| 318 | 318 | super::fill_utf16_buf(|buf, sz| unsafe { c::GetTempPath2W(sz, buf) }, super::os2path).unwrap() |
| 319 | 319 | } |
| 320 | 320 | |
| 321 | #[cfg(not(target_vendor = "uwp"))] | |
| 321 | #[cfg(all(not(target_vendor = "uwp"), not(target_vendor = "win7")))] | |
| 322 | fn home_dir_crt() -> Option<PathBuf> { | |
| 323 | unsafe { | |
| 324 | // Defined in processthreadsapi.h. | |
| 325 | const CURRENT_PROCESS_TOKEN: usize = -4_isize as usize; | |
| 326 | ||
| 327 | super::fill_utf16_buf( | |
| 328 | |buf, mut sz| { | |
| 329 | match c::GetUserProfileDirectoryW( | |
| 330 | ptr::invalid_mut(CURRENT_PROCESS_TOKEN), | |
| 331 | buf, | |
| 332 | &mut sz, | |
| 333 | ) { | |
| 334 | 0 if api::get_last_error().code != c::ERROR_INSUFFICIENT_BUFFER => 0, | |
| 335 | 0 => sz, | |
| 336 | _ => sz - 1, // sz includes the null terminator | |
| 337 | } | |
| 338 | }, | |
| 339 | super::os2path, | |
| 340 | ) | |
| 341 | .ok() | |
| 342 | } | |
| 343 | } | |
| 344 | ||
| 345 | #[cfg(target_vendor = "win7")] | |
| 322 | 346 | fn home_dir_crt() -> Option<PathBuf> { |
| 323 | 347 | unsafe { |
| 324 | // The magic constant -4 can be used as the token passed to GetUserProfileDirectoryW below | |
| 325 | // instead of us having to go through these multiple steps to get a token. However this is | |
| 326 | // not implemented on Windows 7, only Windows 8 and up. When we drop support for Windows 7 | |
| 327 | // we can simplify this code. See #90144 for details. | |
| 328 | 348 | use crate::sys::handle::Handle; |
| 329 | 349 | |
| 330 | 350 | let me = c::GetCurrentProcess(); |
tests/coverage/closure_unit_return.cov-map created+34| ... | ... | @@ -0,0 +1,34 @@ |
| 1 | Function name: closure_unit_return::explicit_unit | |
| 2 | Raw bytes (14): 0x[01, 01, 00, 02, 01, 07, 01, 01, 10, 01, 05, 05, 02, 02] | |
| 3 | Number of files: 1 | |
| 4 | - file 0 => global file 1 | |
| 5 | Number of expressions: 0 | |
| 6 | Number of file 0 mappings: 2 | |
| 7 | - Code(Counter(0)) at (prev + 7, 1) to (start + 1, 16) | |
| 8 | - Code(Counter(0)) at (prev + 5, 5) to (start + 2, 2) | |
| 9 | ||
| 10 | Function name: closure_unit_return::explicit_unit::{closure#0} (unused) | |
| 11 | Raw bytes (9): 0x[01, 01, 00, 01, 00, 08, 16, 02, 06] | |
| 12 | Number of files: 1 | |
| 13 | - file 0 => global file 1 | |
| 14 | Number of expressions: 0 | |
| 15 | Number of file 0 mappings: 1 | |
| 16 | - Code(Zero) at (prev + 8, 22) to (start + 2, 6) | |
| 17 | ||
| 18 | Function name: closure_unit_return::implicit_unit | |
| 19 | Raw bytes (14): 0x[01, 01, 00, 02, 01, 10, 01, 01, 10, 01, 05, 05, 02, 02] | |
| 20 | Number of files: 1 | |
| 21 | - file 0 => global file 1 | |
| 22 | Number of expressions: 0 | |
| 23 | Number of file 0 mappings: 2 | |
| 24 | - Code(Counter(0)) at (prev + 16, 1) to (start + 1, 16) | |
| 25 | - Code(Counter(0)) at (prev + 5, 5) to (start + 2, 2) | |
| 26 | ||
| 27 | Function name: closure_unit_return::implicit_unit::{closure#0} (unused) | |
| 28 | Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 16, 02, 06] | |
| 29 | Number of files: 1 | |
| 30 | - file 0 => global file 1 | |
| 31 | Number of expressions: 0 | |
| 32 | Number of file 0 mappings: 1 | |
| 33 | - Code(Zero) at (prev + 17, 22) to (start + 2, 6) | |
| 34 |
tests/coverage/closure_unit_return.coverage created+30| ... | ... | @@ -0,0 +1,30 @@ |
| 1 | LL| |#![feature(coverage_attribute)] | |
| 2 | LL| |// edition: 2021 | |
| 3 | LL| | | |
| 4 | LL| |// Regression test for an inconsistency between functions that return the value | |
| 5 | LL| |// of their trailing expression, and functions that implicitly return `()`. | |
| 6 | LL| | | |
| 7 | LL| 1|fn explicit_unit() { | |
| 8 | LL| 1| let closure = || { | |
| 9 | LL| 0| (); | |
| 10 | LL| 0| }; | |
| 11 | LL| | | |
| 12 | LL| 1| drop(closure); | |
| 13 | LL| 1| () // explicit return of trailing value | |
| 14 | LL| 1|} | |
| 15 | LL| | | |
| 16 | LL| 1|fn implicit_unit() { | |
| 17 | LL| 1| let closure = || { | |
| 18 | LL| 0| (); | |
| 19 | LL| 0| }; | |
| 20 | LL| | | |
| 21 | LL| 1| drop(closure); | |
| 22 | LL| 1| // implicit return of `()` | |
| 23 | LL| 1|} | |
| 24 | LL| | | |
| 25 | LL| |#[coverage(off)] | |
| 26 | LL| |fn main() { | |
| 27 | LL| | explicit_unit(); | |
| 28 | LL| | implicit_unit(); | |
| 29 | LL| |} | |
| 30 |
tests/coverage/closure_unit_return.rs created+29| ... | ... | @@ -0,0 +1,29 @@ |
| 1 | #![feature(coverage_attribute)] | |
| 2 | // edition: 2021 | |
| 3 | ||
| 4 | // Regression test for an inconsistency between functions that return the value | |
| 5 | // of their trailing expression, and functions that implicitly return `()`. | |
| 6 | ||
| 7 | fn explicit_unit() { | |
| 8 | let closure = || { | |
| 9 | (); | |
| 10 | }; | |
| 11 | ||
| 12 | drop(closure); | |
| 13 | () // explicit return of trailing value | |
| 14 | } | |
| 15 | ||
| 16 | fn implicit_unit() { | |
| 17 | let closure = || { | |
| 18 | (); | |
| 19 | }; | |
| 20 | ||
| 21 | drop(closure); | |
| 22 | // implicit return of `()` | |
| 23 | } | |
| 24 | ||
| 25 | #[coverage(off)] | |
| 26 | fn main() { | |
| 27 | explicit_unit(); | |
| 28 | implicit_unit(); | |
| 29 | } |
tests/coverage/coverage_attr_closure.cov-map+4-4| ... | ... | @@ -15,14 +15,14 @@ Number of file 0 mappings: 1 |
| 15 | 15 | - Code(Zero) at (prev + 29, 19) to (start + 2, 6) |
| 16 | 16 | |
| 17 | 17 | Function name: coverage_attr_closure::contains_closures_on |
| 18 | Raw bytes (19): 0x[01, 01, 00, 03, 01, 0f, 01, 02, 05, 01, 04, 06, 02, 05, 01, 04, 06, 01, 02] | |
| 18 | Raw bytes (19): 0x[01, 01, 00, 03, 01, 0f, 01, 01, 1a, 01, 05, 09, 00, 1b, 01, 04, 01, 00, 02] | |
| 19 | 19 | Number of files: 1 |
| 20 | 20 | - file 0 => global file 1 |
| 21 | 21 | Number of expressions: 0 |
| 22 | 22 | Number of file 0 mappings: 3 |
| 23 | - Code(Counter(0)) at (prev + 15, 1) to (start + 2, 5) | |
| 24 | - Code(Counter(0)) at (prev + 4, 6) to (start + 2, 5) | |
| 25 | - Code(Counter(0)) at (prev + 4, 6) to (start + 1, 2) | |
| 23 | - Code(Counter(0)) at (prev + 15, 1) to (start + 1, 26) | |
| 24 | - Code(Counter(0)) at (prev + 5, 9) to (start + 0, 27) | |
| 25 | - Code(Counter(0)) at (prev + 4, 1) to (start + 0, 2) | |
| 26 | 26 | |
| 27 | 27 | Function name: coverage_attr_closure::contains_closures_on::{closure#0} (unused) |
| 28 | 28 | Raw bytes (9): 0x[01, 01, 00, 01, 00, 11, 13, 02, 06] |
tests/coverage/coverage_attr_closure.coverage+4-4| ... | ... | @@ -14,13 +14,13 @@ |
| 14 | 14 | LL| |#[coverage(on)] |
| 15 | 15 | LL| 1|fn contains_closures_on() { |
| 16 | 16 | LL| 1| let _local_closure_on = #[coverage(on)] |
| 17 | LL| 1| |input: &str| { | |
| 17 | LL| 0| |input: &str| { | |
| 18 | 18 | LL| 0| println!("{input}"); |
| 19 | LL| 1| }; | |
| 19 | LL| 0| }; | |
| 20 | 20 | LL| 1| let _local_closure_off = #[coverage(off)] |
| 21 | LL| 1| |input: &str| { | |
| 21 | LL| | |input: &str| { | |
| 22 | 22 | LL| | println!("{input}"); |
| 23 | LL| 1| }; | |
| 23 | LL| | }; | |
| 24 | 24 | LL| 1|} |
| 25 | 25 | LL| | |
| 26 | 26 | LL| |#[coverage(off)] |
tests/coverage/inline-dead.cov-map+3-3| ... | ... | @@ -22,13 +22,13 @@ Number of file 0 mappings: 4 |
| 22 | 22 | = (Zero + (c0 - Zero)) |
| 23 | 23 | |
| 24 | 24 | Function name: inline_dead::main |
| 25 | Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 01, 03, 0d, 01, 05, 06, 02, 02] | |
| 25 | Raw bytes (14): 0x[01, 01, 00, 02, 01, 04, 01, 03, 0a, 01, 06, 05, 01, 02] | |
| 26 | 26 | Number of files: 1 |
| 27 | 27 | - file 0 => global file 1 |
| 28 | 28 | Number of expressions: 0 |
| 29 | 29 | Number of file 0 mappings: 2 |
| 30 | - Code(Counter(0)) at (prev + 4, 1) to (start + 3, 13) | |
| 31 | - Code(Counter(0)) at (prev + 5, 6) to (start + 2, 2) | |
| 30 | - Code(Counter(0)) at (prev + 4, 1) to (start + 3, 10) | |
| 31 | - Code(Counter(0)) at (prev + 6, 5) to (start + 1, 2) | |
| 32 | 32 | |
| 33 | 33 | Function name: inline_dead::main::{closure#0} |
| 34 | 34 | Raw bytes (23): 0x[01, 01, 02, 00, 06, 01, 00, 03, 01, 07, 17, 01, 16, 00, 01, 17, 00, 18, 03, 01, 05, 00, 06] |
tests/coverage/macro_name_span.cov-map+2-2| ... | ... | @@ -1,10 +1,10 @@ |
| 1 | 1 | Function name: macro_name_span::affected_function |
| 2 | Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 1c, 02, 06] | |
| 2 | Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 1c, 01, 40] | |
| 3 | 3 | Number of files: 1 |
| 4 | 4 | - file 0 => global file 1 |
| 5 | 5 | Number of expressions: 0 |
| 6 | 6 | Number of file 0 mappings: 1 |
| 7 | - Code(Counter(0)) at (prev + 22, 28) to (start + 2, 6) | |
| 7 | - Code(Counter(0)) at (prev + 22, 28) to (start + 1, 64) | |
| 8 | 8 | |
| 9 | 9 | Function name: macro_name_span::main |
| 10 | 10 | Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 01, 02, 02] |
tests/coverage/macro_name_span.coverage+1-1| ... | ... | @@ -21,6 +21,6 @@ |
| 21 | 21 | LL| |macro_name_span_helper::macro_that_defines_a_function! { |
| 22 | 22 | LL| 1| fn affected_function() { |
| 23 | 23 | LL| 1| macro_with_an_unreasonably_and_egregiously_long_name!(); |
| 24 | LL| 1| } | |
| 24 | LL| | } | |
| 25 | 25 | LL| |} |
| 26 | 26 |
tests/coverage/unicode.cov-map-8| ... | ... | @@ -27,14 +27,6 @@ Number of file 0 mappings: 9 |
| 27 | 27 | - Code(Expression(5, Add)) at (prev + 2, 5) to (start + 1, 2) |
| 28 | 28 | = (c4 + ((((c0 + c1) - c1) - c2) + c3)) |
| 29 | 29 | |
| 30 | Function name: unicode::サビ | |
| 31 | Raw bytes (9): 0x[01, 01, 00, 01, 01, 1e, 14, 00, 18] | |
| 32 | Number of files: 1 | |
| 33 | - file 0 => global file 1 | |
| 34 | Number of expressions: 0 | |
| 35 | Number of file 0 mappings: 1 | |
| 36 | - Code(Counter(0)) at (prev + 30, 20) to (start + 0, 24) | |
| 37 | ||
| 38 | 30 | Function name: unicode::他 (unused) |
| 39 | 31 | Raw bytes (9): 0x[01, 01, 00, 01, 00, 1e, 19, 00, 25] |
| 40 | 32 | Number of files: 1 |
tests/coverage/unicode.coverage+1-2| ... | ... | @@ -29,8 +29,7 @@ |
| 29 | 29 | LL| | |
| 30 | 30 | LL| |macro_rules! macro_that_defines_a_function { |
| 31 | 31 | LL| | (fn $名:ident () $体:tt) => { |
| 32 | LL| [0;35m1[0m| fn $名 () $体 [0;41mfn 他 () {}[0m | |
| 33 | ^0 | |
| 32 | LL| 0| fn $名 () $体 [0;41mfn 他 () {}[0m | |
| 34 | 33 | LL| | } |
| 35 | 34 | LL| |} |
| 36 | 35 | LL| | |
tests/ui/consts/const-ref-to-static-linux-vtable.rs created+43| ... | ... | @@ -0,0 +1,43 @@ |
| 1 | //@check-pass | |
| 2 | //! This is the reduced version of the "Linux kernel vtable" use-case. | |
| 3 | #![feature(const_mut_refs, const_refs_to_static)] | |
| 4 | use std::ptr::addr_of_mut; | |
| 5 | ||
| 6 | #[repr(C)] | |
| 7 | struct ThisModule(i32); | |
| 8 | ||
| 9 | trait Module { | |
| 10 | const THIS_MODULE_PTR: *mut ThisModule; | |
| 11 | } | |
| 12 | ||
| 13 | struct MyModule; | |
| 14 | ||
| 15 | // Generated by a macro. | |
| 16 | extern "C" { | |
| 17 | static mut THIS_MODULE: ThisModule; | |
| 18 | } | |
| 19 | ||
| 20 | // Generated by a macro. | |
| 21 | impl Module for MyModule { | |
| 22 | const THIS_MODULE_PTR: *mut ThisModule = unsafe { addr_of_mut!(THIS_MODULE) }; | |
| 23 | } | |
| 24 | ||
| 25 | struct Vtable { | |
| 26 | module: *mut ThisModule, | |
| 27 | foo_fn: fn(*mut ()) -> i32, | |
| 28 | } | |
| 29 | ||
| 30 | trait Foo { | |
| 31 | type Mod: Module; | |
| 32 | ||
| 33 | fn foo(&mut self) -> i32; | |
| 34 | } | |
| 35 | ||
| 36 | fn generate_vtable<T: Foo>() -> &'static Vtable { | |
| 37 | &Vtable { | |
| 38 | module: T::Mod::THIS_MODULE_PTR, | |
| 39 | foo_fn: |ptr| unsafe { &mut *ptr.cast::<T>() }.foo(), | |
| 40 | } | |
| 41 | } | |
| 42 | ||
| 43 | fn main() {} |
tests/ui/consts/issue-17718-const-bad-values.rs+1| ... | ... | @@ -6,5 +6,6 @@ const C1: &'static mut [usize] = &mut []; |
| 6 | 6 | static mut S: usize = 3; |
| 7 | 7 | const C2: &'static mut usize = unsafe { &mut S }; |
| 8 | 8 | //~^ ERROR: referencing statics in constants |
| 9 | //~| ERROR: mutable references are not allowed | |
| 9 | 10 | |
| 10 | 11 | fn main() {} |
tests/ui/consts/issue-17718-const-bad-values.stderr+11-1| ... | ... | @@ -16,7 +16,17 @@ LL | const C2: &'static mut usize = unsafe { &mut S }; |
| 16 | 16 | = note: `static` and `const` variables can refer to other `const` variables. A `const` variable, however, cannot refer to a `static` variable. |
| 17 | 17 | = help: to fix this, the value can be extracted to a `const` and then used. |
| 18 | 18 | |
| 19 | error: aborting due to 2 previous errors | |
| 19 | error[E0658]: mutable references are not allowed in constants | |
| 20 | --> $DIR/issue-17718-const-bad-values.rs:7:41 | |
| 21 | | | |
| 22 | LL | const C2: &'static mut usize = unsafe { &mut S }; | |
| 23 | | ^^^^^^ | |
| 24 | | | |
| 25 | = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information | |
| 26 | = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable | |
| 27 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date | |
| 28 | ||
| 29 | error: aborting due to 3 previous errors | |
| 20 | 30 | |
| 21 | 31 | Some errors have detailed explanations: E0658, E0764. |
| 22 | 32 | For more information about an error, try `rustc --explain E0658`. |
tests/ui/consts/miri_unleashed/box.stderr+1-1| ... | ... | @@ -16,7 +16,7 @@ help: skipping check for `const_mut_refs` feature |
| 16 | 16 | | |
| 17 | 17 | LL | &mut *(Box::new(0)) |
| 18 | 18 | | ^^^^^^^^^^^^^^^^^^^ |
| 19 | help: skipping check that does not even have a feature gate | |
| 19 | help: skipping check for `const_mut_refs` feature | |
| 20 | 20 | --> $DIR/box.rs:8:5 |
| 21 | 21 | | |
| 22 | 22 | LL | &mut *(Box::new(0)) |
tests/ui/consts/miri_unleashed/mutable_references_err.32bit.stderr+1-1| ... | ... | @@ -114,7 +114,7 @@ help: skipping check for `const_refs_to_static` feature |
| 114 | 114 | | |
| 115 | 115 | LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; |
| 116 | 116 | | ^^^ |
| 117 | help: skipping check that does not even have a feature gate | |
| 117 | help: skipping check for `const_mut_refs` feature | |
| 118 | 118 | --> $DIR/mutable_references_err.rs:32:35 |
| 119 | 119 | | |
| 120 | 120 | LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; |
tests/ui/consts/miri_unleashed/mutable_references_err.64bit.stderr+1-1| ... | ... | @@ -114,7 +114,7 @@ help: skipping check for `const_refs_to_static` feature |
| 114 | 114 | | |
| 115 | 115 | LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; |
| 116 | 116 | | ^^^ |
| 117 | help: skipping check that does not even have a feature gate | |
| 117 | help: skipping check for `const_mut_refs` feature | |
| 118 | 118 | --> $DIR/mutable_references_err.rs:32:35 |
| 119 | 119 | | |
| 120 | 120 | LL | const SUBTLE: &mut i32 = unsafe { &mut FOO }; |
tests/ui/consts/mut-ptr-to-static.rs created+40| ... | ... | @@ -0,0 +1,40 @@ |
| 1 | //@run-pass | |
| 2 | #![feature(const_mut_refs)] | |
| 3 | #![feature(sync_unsafe_cell)] | |
| 4 | ||
| 5 | use std::cell::SyncUnsafeCell; | |
| 6 | use std::ptr; | |
| 7 | ||
| 8 | #[repr(C)] | |
| 9 | struct SyncPtr { | |
| 10 | foo: *mut u32, | |
| 11 | } | |
| 12 | unsafe impl Sync for SyncPtr {} | |
| 13 | ||
| 14 | static mut STATIC: u32 = 42; | |
| 15 | ||
| 16 | static INTERIOR_MUTABLE_STATIC: SyncUnsafeCell<u32> = SyncUnsafeCell::new(42); | |
| 17 | ||
| 18 | // A static that mutably points to STATIC. | |
| 19 | static PTR: SyncPtr = SyncPtr { | |
| 20 | foo: unsafe { ptr::addr_of_mut!(STATIC) }, | |
| 21 | }; | |
| 22 | static INTERIOR_MUTABLE_PTR: SyncPtr = SyncPtr { | |
| 23 | foo: ptr::addr_of!(INTERIOR_MUTABLE_STATIC) as *mut u32, | |
| 24 | }; | |
| 25 | ||
| 26 | fn main() { | |
| 27 | let ptr = PTR.foo; | |
| 28 | unsafe { | |
| 29 | assert_eq!(*ptr, 42); | |
| 30 | *ptr = 0; | |
| 31 | assert_eq!(*PTR.foo, 0); | |
| 32 | } | |
| 33 | ||
| 34 | let ptr = INTERIOR_MUTABLE_PTR.foo; | |
| 35 | unsafe { | |
| 36 | assert_eq!(*ptr, 42); | |
| 37 | *ptr = 0; | |
| 38 | assert_eq!(*INTERIOR_MUTABLE_PTR.foo, 0); | |
| 39 | } | |
| 40 | } |
tests/ui/error-codes/E0017.rs+4-4| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | #![feature(const_mut_refs)] | |
| 2 | ||
| 1 | 3 | static X: i32 = 1; |
| 2 | 4 | const C: i32 = 2; |
| 3 | 5 | static mut M: i32 = 3; |
| ... | ... | @@ -5,14 +7,12 @@ static mut M: i32 = 3; |
| 5 | 7 | const CR: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed |
| 6 | 8 | //~| WARN taking a mutable |
| 7 | 9 | |
| 8 | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658 | |
| 9 | //~| ERROR cannot borrow | |
| 10 | //~| ERROR mutable references are not allowed | |
| 10 | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR cannot borrow immutable static item `X` as mutable | |
| 11 | 11 | |
| 12 | 12 | static CONST_REF: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed |
| 13 | 13 | //~| WARN taking a mutable |
| 14 | 14 | |
| 15 | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR mutable references are not | |
| 15 | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; | |
| 16 | 16 | //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref] |
| 17 | 17 | |
| 18 | 18 | fn main() {} |
tests/ui/error-codes/E0017.stderr+7-29| ... | ... | @@ -14,7 +14,7 @@ LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { addr_of_mut!(M) }; |
| 14 | 14 | | ~~~~~~~~~~~~~~~ |
| 15 | 15 | |
| 16 | 16 | warning: taking a mutable reference to a `const` item |
| 17 | --> $DIR/E0017.rs:5:30 | |
| 17 | --> $DIR/E0017.rs:7:30 | |
| 18 | 18 | | |
| 19 | 19 | LL | const CR: &'static mut i32 = &mut C; |
| 20 | 20 | | ^^^^^^ |
| ... | ... | @@ -22,36 +22,20 @@ LL | const CR: &'static mut i32 = &mut C; |
| 22 | 22 | = note: each usage of a `const` item creates a new temporary |
| 23 | 23 | = note: the mutable reference will refer to this temporary, not the original `const` item |
| 24 | 24 | note: `const` item defined here |
| 25 | --> $DIR/E0017.rs:2:1 | |
| 25 | --> $DIR/E0017.rs:4:1 | |
| 26 | 26 | | |
| 27 | 27 | LL | const C: i32 = 2; |
| 28 | 28 | | ^^^^^^^^^^^^ |
| 29 | 29 | = note: `#[warn(const_item_mutation)]` on by default |
| 30 | 30 | |
| 31 | 31 | error[E0764]: mutable references are not allowed in the final value of constants |
| 32 | --> $DIR/E0017.rs:5:30 | |
| 32 | --> $DIR/E0017.rs:7:30 | |
| 33 | 33 | | |
| 34 | 34 | LL | const CR: &'static mut i32 = &mut C; |
| 35 | 35 | | ^^^^^^ |
| 36 | 36 | |
| 37 | error[E0658]: mutation through a reference is not allowed in statics | |
| 38 | --> $DIR/E0017.rs:8:39 | |
| 39 | | | |
| 40 | LL | static STATIC_REF: &'static mut i32 = &mut X; | |
| 41 | | ^^^^^^ | |
| 42 | | | |
| 43 | = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information | |
| 44 | = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable | |
| 45 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date | |
| 46 | ||
| 47 | error[E0764]: mutable references are not allowed in the final value of statics | |
| 48 | --> $DIR/E0017.rs:8:39 | |
| 49 | | | |
| 50 | LL | static STATIC_REF: &'static mut i32 = &mut X; | |
| 51 | | ^^^^^^ | |
| 52 | ||
| 53 | 37 | error[E0596]: cannot borrow immutable static item `X` as mutable |
| 54 | --> $DIR/E0017.rs:8:39 | |
| 38 | --> $DIR/E0017.rs:10:39 | |
| 55 | 39 | | |
| 56 | 40 | LL | static STATIC_REF: &'static mut i32 = &mut X; |
| 57 | 41 | | ^^^^^^ cannot borrow as mutable |
| ... | ... | @@ -65,7 +49,7 @@ LL | static CONST_REF: &'static mut i32 = &mut C; |
| 65 | 49 | = note: each usage of a `const` item creates a new temporary |
| 66 | 50 | = note: the mutable reference will refer to this temporary, not the original `const` item |
| 67 | 51 | note: `const` item defined here |
| 68 | --> $DIR/E0017.rs:2:1 | |
| 52 | --> $DIR/E0017.rs:4:1 | |
| 69 | 53 | | |
| 70 | 54 | LL | const C: i32 = 2; |
| 71 | 55 | | ^^^^^^^^^^^^ |
| ... | ... | @@ -76,13 +60,7 @@ error[E0764]: mutable references are not allowed in the final value of statics |
| 76 | 60 | LL | static CONST_REF: &'static mut i32 = &mut C; |
| 77 | 61 | | ^^^^^^ |
| 78 | 62 | |
| 79 | error[E0764]: mutable references are not allowed in the final value of statics | |
| 80 | --> $DIR/E0017.rs:15:52 | |
| 81 | | | |
| 82 | LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; | |
| 83 | | ^^^^^^ | |
| 84 | ||
| 85 | error: aborting due to 6 previous errors; 3 warnings emitted | |
| 63 | error: aborting due to 3 previous errors; 3 warnings emitted | |
| 86 | 64 | |
| 87 | Some errors have detailed explanations: E0596, E0658, E0764. | |
| 65 | Some errors have detailed explanations: E0596, E0764. | |
| 88 | 66 | For more information about an error, try `rustc --explain E0596`. |
tests/ui/error-codes/E0388.rs+1-3| ... | ... | @@ -3,9 +3,7 @@ const C: i32 = 2; |
| 3 | 3 | |
| 4 | 4 | const CR: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed |
| 5 | 5 | //~| WARN taking a mutable |
| 6 | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR cannot borrow | |
| 7 | //~| ERROR E0658 | |
| 8 | //~| ERROR mutable references are not allowed | |
| 6 | static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658 | |
| 9 | 7 | |
| 10 | 8 | static CONST_REF: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed |
| 11 | 9 | //~| WARN taking a mutable |
tests/ui/error-codes/E0388.stderr+6-18| ... | ... | @@ -19,7 +19,7 @@ error[E0764]: mutable references are not allowed in the final value of constants |
| 19 | 19 | LL | const CR: &'static mut i32 = &mut C; |
| 20 | 20 | | ^^^^^^ |
| 21 | 21 | |
| 22 | error[E0658]: mutation through a reference is not allowed in statics | |
| 22 | error[E0658]: mutable references are not allowed in statics | |
| 23 | 23 | --> $DIR/E0388.rs:6:39 |
| 24 | 24 | | |
| 25 | 25 | LL | static STATIC_REF: &'static mut i32 = &mut X; |
| ... | ... | @@ -29,20 +29,8 @@ LL | static STATIC_REF: &'static mut i32 = &mut X; |
| 29 | 29 | = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable |
| 30 | 30 | = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date |
| 31 | 31 | |
| 32 | error[E0764]: mutable references are not allowed in the final value of statics | |
| 33 | --> $DIR/E0388.rs:6:39 | |
| 34 | | | |
| 35 | LL | static STATIC_REF: &'static mut i32 = &mut X; | |
| 36 | | ^^^^^^ | |
| 37 | ||
| 38 | error[E0596]: cannot borrow immutable static item `X` as mutable | |
| 39 | --> $DIR/E0388.rs:6:39 | |
| 40 | | | |
| 41 | LL | static STATIC_REF: &'static mut i32 = &mut X; | |
| 42 | | ^^^^^^ cannot borrow as mutable | |
| 43 | ||
| 44 | 32 | warning: taking a mutable reference to a `const` item |
| 45 | --> $DIR/E0388.rs:10:38 | |
| 33 | --> $DIR/E0388.rs:8:38 | |
| 46 | 34 | | |
| 47 | 35 | LL | static CONST_REF: &'static mut i32 = &mut C; |
| 48 | 36 | | ^^^^^^ |
| ... | ... | @@ -56,12 +44,12 @@ LL | const C: i32 = 2; |
| 56 | 44 | | ^^^^^^^^^^^^ |
| 57 | 45 | |
| 58 | 46 | error[E0764]: mutable references are not allowed in the final value of statics |
| 59 | --> $DIR/E0388.rs:10:38 | |
| 47 | --> $DIR/E0388.rs:8:38 | |
| 60 | 48 | | |
| 61 | 49 | LL | static CONST_REF: &'static mut i32 = &mut C; |
| 62 | 50 | | ^^^^^^ |
| 63 | 51 | |
| 64 | error: aborting due to 5 previous errors; 2 warnings emitted | |
| 52 | error: aborting due to 3 previous errors; 2 warnings emitted | |
| 65 | 53 | |
| 66 | Some errors have detailed explanations: E0596, E0658, E0764. | |
| 67 | For more information about an error, try `rustc --explain E0596`. | |
| 54 | Some errors have detailed explanations: E0658, E0764. | |
| 55 | For more information about an error, try `rustc --explain E0658`. |
tests/ui/intrinsics/safe-intrinsic-mismatch.rs+4-4| ... | ... | @@ -5,12 +5,12 @@ |
| 5 | 5 | extern "rust-intrinsic" { |
| 6 | 6 | fn size_of<T>() -> usize; //~ ERROR intrinsic safety mismatch |
| 7 | 7 | //~^ ERROR intrinsic safety mismatch |
| 8 | ||
| 9 | #[rustc_safe_intrinsic] | |
| 10 | fn assume(b: bool); //~ ERROR intrinsic safety mismatch | |
| 11 | //~^ ERROR intrinsic safety mismatch | |
| 12 | 8 | } |
| 13 | 9 | |
| 10 | #[rustc_intrinsic] | |
| 11 | const fn assume(_b: bool) {} //~ ERROR intrinsic safety mismatch | |
| 12 | //~| ERROR intrinsic has wrong type | |
| 13 | ||
| 14 | 14 | #[rustc_intrinsic] |
| 15 | 15 | const fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {} |
| 16 | 16 | //~^ ERROR intrinsic safety mismatch |
tests/ui/intrinsics/safe-intrinsic-mismatch.stderr+11-10| ... | ... | @@ -4,12 +4,6 @@ error: intrinsic safety mismatch between list of intrinsics within the compiler |
| 4 | 4 | LL | fn size_of<T>() -> usize; |
| 5 | 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^ |
| 6 | 6 | |
| 7 | error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `assume` | |
| 8 | --> $DIR/safe-intrinsic-mismatch.rs:10:5 | |
| 9 | | | |
| 10 | LL | fn assume(b: bool); | |
| 11 | | ^^^^^^^^^^^^^^^^^^ | |
| 12 | ||
| 13 | 7 | error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `size_of` |
| 14 | 8 | --> $DIR/safe-intrinsic-mismatch.rs:6:5 |
| 15 | 9 | | |
| ... | ... | @@ -19,12 +13,19 @@ LL | fn size_of<T>() -> usize; |
| 19 | 13 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` |
| 20 | 14 | |
| 21 | 15 | error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `assume` |
| 22 | --> $DIR/safe-intrinsic-mismatch.rs:10:5 | |
| 16 | --> $DIR/safe-intrinsic-mismatch.rs:11:1 | |
| 23 | 17 | | |
| 24 | LL | fn assume(b: bool); | |
| 25 | | ^^^^^^^^^^^^^^^^^^ | |
| 18 | LL | const fn assume(_b: bool) {} | |
| 19 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| 20 | ||
| 21 | error[E0308]: intrinsic has wrong type | |
| 22 | --> $DIR/safe-intrinsic-mismatch.rs:11:16 | |
| 26 | 23 | | |
| 27 | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` | |
| 24 | LL | const fn assume(_b: bool) {} | |
| 25 | | ^ expected unsafe fn, found normal fn | |
| 26 | | | |
| 27 | = note: expected signature `unsafe fn(_)` | |
| 28 | found signature `fn(_)` | |
| 28 | 29 | |
| 29 | 30 | error: intrinsic safety mismatch between list of intrinsics within the compiler and core library intrinsics for intrinsic `const_deallocate` |
| 30 | 31 | --> $DIR/safe-intrinsic-mismatch.rs:15:1 |
tests/ui/reify-intrinsic.rs+2-3| ... | ... | @@ -13,10 +13,9 @@ fn b() { |
| 13 | 13 | } |
| 14 | 14 | |
| 15 | 15 | fn c() { |
| 16 | let _ = [ | |
| 17 | std::intrinsics::likely, | |
| 16 | let _: [unsafe extern "rust-intrinsic" fn(bool) -> bool; 2] = [ | |
| 17 | std::intrinsics::likely, //~ ERROR cannot coerce | |
| 18 | 18 | std::intrinsics::unlikely, |
| 19 | //~^ ERROR cannot coerce | |
| 20 | 19 | ]; |
| 21 | 20 | } |
| 22 | 21 |
tests/ui/reify-intrinsic.stderr+5-6| ... | ... | @@ -16,14 +16,13 @@ LL | let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) |
| 16 | 16 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 17 | 17 | |
| 18 | 18 | error[E0308]: cannot coerce intrinsics to function pointers |
| 19 | --> $DIR/reify-intrinsic.rs:18:9 | |
| 19 | --> $DIR/reify-intrinsic.rs:17:9 | |
| 20 | 20 | | |
| 21 | LL | std::intrinsics::unlikely, | |
| 22 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers | |
| 21 | LL | std::intrinsics::likely, | |
| 22 | | ^^^^^^^^^^^^^^^^^^^^^^^ cannot coerce intrinsics to function pointers | |
| 23 | 23 | | |
| 24 | = note: expected fn item `extern "rust-intrinsic" fn(_) -> _ {likely}` | |
| 25 | found fn item `extern "rust-intrinsic" fn(_) -> _ {unlikely}` | |
| 26 | = note: different fn items have unique types, even if their signatures are the same | |
| 24 | = note: expected fn pointer `unsafe extern "rust-intrinsic" fn(_) -> _` | |
| 25 | found fn item `fn(_) -> _ {likely}` | |
| 27 | 26 | |
| 28 | 27 | error: aborting due to 3 previous errors |
| 29 | 28 |
triagebot.toml+7-2| ... | ... | @@ -480,12 +480,16 @@ cc = ["@lcnr", "@compiler-errors"] |
| 480 | 480 | message = "Some changes occurred in diagnostic error codes" |
| 481 | 481 | cc = ["@GuillaumeGomez"] |
| 482 | 482 | |
| 483 | [mentions."compiler/rustc_mir_build/src/build/matches"] | |
| 484 | message = "Some changes occurred in match lowering" | |
| 485 | cc = ["@Nadrieril"] | |
| 486 | ||
| 483 | 487 | [mentions."compiler/rustc_mir_build/src/thir/pattern"] |
| 484 | message = "Some changes might have occurred in exhaustiveness checking" | |
| 488 | message = "Some changes occurred in match checking" | |
| 485 | 489 | cc = ["@Nadrieril"] |
| 486 | 490 | |
| 487 | 491 | [mentions."compiler/rustc_pattern_analysis"] |
| 488 | message = "Some changes might have occurred in exhaustiveness checking" | |
| 492 | message = "Some changes occurred in exhaustiveness checking" | |
| 489 | 493 | cc = ["@Nadrieril"] |
| 490 | 494 | |
| 491 | 495 | [mentions."library/core/src/intrinsics/simd.rs"] |
| ... | ... | @@ -659,6 +663,7 @@ compiler-team = [ |
| 659 | 663 | ] |
| 660 | 664 | compiler-team-contributors = [ |
| 661 | 665 | "@TaKO8Ki", |
| 666 | "@Nadrieril", | |
| 662 | 667 | "@nnethercote", |
| 663 | 668 | "@fmease", |
| 664 | 669 | ] |