From c36ff28d4214c65df55cb1d9d8085b34d33d37fb Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 19 Nov 2022 03:28:56 +0000 Subject: [PATCH] drive-by: PolyExistentialPredicate --- .../rustc_const_eval/src/util/type_name.rs | 2 +- .../rustc_hir_analysis/src/astconv/mod.rs | 2 +- compiler/rustc_hir_typeck/src/coercion.rs | 2 +- .../src/infer/error_reporting/mod.rs | 2 +- compiler/rustc_lint/src/context.rs | 2 +- compiler/rustc_middle/src/ty/codec.rs | 4 +-- compiler/rustc_middle/src/ty/context.rs | 30 ++++++++----------- compiler/rustc_middle/src/ty/error.rs | 4 +-- compiler/rustc_middle/src/ty/mod.rs | 7 +++-- compiler/rustc_middle/src/ty/print/mod.rs | 6 ++-- compiler/rustc_middle/src/ty/print/pretty.rs | 8 ++--- compiler/rustc_middle/src/ty/relate.rs | 2 +- .../rustc_middle/src/ty/structural_impls.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 6 ++-- compiler/rustc_symbol_mangling/src/legacy.rs | 2 +- .../src/typeid/typeid_itanium_cxx_abi.rs | 10 +++---- compiler/rustc_symbol_mangling/src/v0.rs | 2 +- .../rustc_trait_selection/src/traits/wf.rs | 4 +-- compiler/rustc_traits/src/chalk/lowering.rs | 2 +- src/tools/clippy/clippy_lints/src/ptr.rs | 2 +- 20 files changed, 48 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_const_eval/src/util/type_name.rs b/compiler/rustc_const_eval/src/util/type_name.rs index 08a6d69b8e4..14c8c88028b 100644 --- a/compiler/rustc_const_eval/src/util/type_name.rs +++ b/compiler/rustc_const_eval/src/util/type_name.rs @@ -74,7 +74,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { fn print_dyn_existential( self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>, ) -> Result { self.pretty_print_dyn_existential(predicates) } diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 16c40cf1299..e3d9ccb7d6e 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -3019,7 +3019,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { fn compute_object_lifetime_bound( &self, span: Span, - existential_predicates: &'tcx ty::List>>, + existential_predicates: &'tcx ty::List>, ) -> Option> // if None, use the default { let tcx = self.tcx(); diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index c1e4ab600f3..894879d7774 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -748,7 +748,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { &self, a: Ty<'tcx>, b: Ty<'tcx>, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>, b_region: ty::Region<'tcx>, ) -> CoerceResult<'tcx> { if !self.tcx.features().dyn_star { diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 22f32251f6d..e03a4ea8247 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -542,7 +542,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { fn print_dyn_existential( self, - _predicates: &'tcx ty::List>>, + _predicates: &'tcx ty::List>, ) -> Result { Err(NonTrivialPath) } diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 28f6ac61c5b..589b4d6a10f 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -1159,7 +1159,7 @@ impl<'tcx> LateContext<'tcx> { fn print_dyn_existential( self, - _predicates: &'tcx ty::List>>, + _predicates: &'tcx ty::List>, ) -> Result { Ok(()) } diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 7263e8306cf..b469eebfad9 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -298,7 +298,7 @@ impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for ty::List>> RefDecodable<'tcx, D> - for ty::List>> + for ty::List> { fn decode(decoder: &mut D) -> &'tcx Self { let len = decoder.read_usize(); @@ -379,7 +379,7 @@ impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> impl_decodable_via_ref! { &'tcx ty::TypeckResults<'tcx>, &'tcx ty::List>, - &'tcx ty::List>>, + &'tcx ty::List>, &'tcx traits::ImplSource<'tcx, ()>, &'tcx mir::Body<'tcx>, &'tcx mir::UnsafetyCheckResult, diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 1c714f59425..13695089eb8 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -17,11 +17,11 @@ use crate::traits; use crate::ty::query::{self, TyCtxtAt}; use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, BindingMode, BoundVar, CanonicalPolyFnSig, - ClosureSizeProfileData, Const, ConstS, ConstVid, DefIdTree, ExistentialPredicate, FloatTy, - FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy, IntTy, IntVar, IntVid, List, - ParamConst, ParamTy, PolyFnSig, Predicate, PredicateKind, PredicateS, ProjectionTy, Region, - RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, UintTy, - Visibility, + ClosureSizeProfileData, Const, ConstS, ConstVid, DefIdTree, FloatTy, FloatVar, FloatVid, + GenericParamDefKind, InferConst, InferTy, IntTy, IntVar, IntVid, List, ParamConst, ParamTy, + PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicateS, ProjectionTy, + Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut, + UintTy, Visibility, }; use crate::ty::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef, UserSubsts}; use rustc_ast as ast; @@ -109,7 +109,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type Mutability = hir::Mutability; type Movability = hir::Movability; type PolyFnSig = PolyFnSig<'tcx>; - type ListBinderExistentialPredicate = &'tcx List>>; + type ListBinderExistentialPredicate = &'tcx List>; type BinderListTy = Binder<'tcx, &'tcx List>>; type ListTy = &'tcx List>; type ProjectionTy = ty::ProjectionTy<'tcx>; @@ -140,8 +140,7 @@ pub struct CtxtInterners<'tcx> { substs: InternedSet<'tcx, InternalSubsts<'tcx>>, canonical_var_infos: InternedSet<'tcx, List>>, region: InternedSet<'tcx, RegionKind<'tcx>>, - poly_existential_predicates: - InternedSet<'tcx, List>>>, + poly_existential_predicates: InternedSet<'tcx, List>>, predicate: InternedSet<'tcx, PredicateS<'tcx>>, predicates: InternedSet<'tcx, List>>, projs: InternedSet<'tcx, List>, @@ -1810,7 +1809,7 @@ nop_lift! {const_; Const<'a> => Const<'tcx>} nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>} nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>} -nop_list_lift! {poly_existential_predicates; ty::Binder<'a, ExistentialPredicate<'a>> => ty::Binder<'tcx, ExistentialPredicate<'tcx>>} +nop_list_lift! {poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>} nop_list_lift! {predicates; Predicate<'a> => Predicate<'tcx>} nop_list_lift! {canonical_var_infos; CanonicalVarInfo<'a> => CanonicalVarInfo<'tcx>} nop_list_lift! {projs; ProjectionKind => ProjectionKind} @@ -2265,7 +2264,7 @@ slice_interners!( substs: _intern_substs(GenericArg<'tcx>), canonical_var_infos: _intern_canonical_var_infos(CanonicalVarInfo<'tcx>), poly_existential_predicates: - _intern_poly_existential_predicates(ty::Binder<'tcx, ExistentialPredicate<'tcx>>), + _intern_poly_existential_predicates(PolyExistentialPredicate<'tcx>), predicates: _intern_predicates(Predicate<'tcx>), projs: _intern_projs(ProjectionKind), place_elems: _intern_place_elems(PlaceElem<'tcx>), @@ -2544,7 +2543,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_dynamic( self, - obj: &'tcx List>>, + obj: &'tcx List>, reg: ty::Region<'tcx>, repr: DynKind, ) -> Ty<'tcx> { @@ -2682,8 +2681,8 @@ impl<'tcx> TyCtxt<'tcx> { pub fn intern_poly_existential_predicates( self, - eps: &[ty::Binder<'tcx, ExistentialPredicate<'tcx>>], - ) -> &'tcx List>> { + eps: &[PolyExistentialPredicate<'tcx>], + ) -> &'tcx List> { assert!(!eps.is_empty()); assert!( eps.array_windows() @@ -2767,10 +2766,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn mk_poly_existential_predicates< - I: InternAs< - [ty::Binder<'tcx, ExistentialPredicate<'tcx>>], - &'tcx List>>, - >, + I: InternAs<[PolyExistentialPredicate<'tcx>], &'tcx List>>, >( self, iter: I, diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs index dc13374f992..61cfcbe7019 100644 --- a/compiler/rustc_middle/src/ty/error.rs +++ b/compiler/rustc_middle/src/ty/error.rs @@ -64,9 +64,7 @@ pub enum TypeError<'tcx> { CyclicTy(Ty<'tcx>), CyclicConst(ty::Const<'tcx>), ProjectionMismatched(ExpectedFound), - ExistentialMismatch( - ExpectedFound<&'tcx ty::List>>>, - ), + ExistentialMismatch(ExpectedFound<&'tcx ty::List>>), ObjectUnsafeCoercion(DefId), ConstMismatch(ExpectedFound>), diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f9a762261e2..99b830da096 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -94,9 +94,10 @@ pub use self::sty::{ BoundVariableKind, CanonicalPolyFnSig, ClosureSubsts, ClosureSubstsParts, ConstVid, EarlyBoundRegion, ExistentialPredicate, ExistentialProjection, ExistentialTraitRef, FnSig, FreeRegion, GenSig, GeneratorSubsts, GeneratorSubstsParts, InlineConstSubsts, - InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialProjection, - PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, ProjectionTy, Region, RegionKind, - RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, VarianceDiagInfo, + InlineConstSubstsParts, ParamConst, ParamTy, PolyExistentialPredicate, + PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyGenSig, PolyTraitRef, + ProjectionTy, Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarSubsts, + VarianceDiagInfo, }; pub use self::trait_def::TraitDef; diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 44b9548db89..667298b9b5b 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -63,7 +63,7 @@ pub trait Printer<'tcx>: Sized { fn print_dyn_existential( self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>, ) -> Result; fn print_const(self, ct: ty::Const<'tcx>) -> Result; @@ -308,9 +308,7 @@ impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for Ty<'tcx> { } } -impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> - for &'tcx ty::List>> -{ +impl<'tcx, P: Printer<'tcx>> Print<'tcx, P> for &'tcx ty::List> { type Output = P::DynExistential; type Error = P::Error; fn print(&self, cx: P) -> Result { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 48e803597b0..ef30b743f55 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1059,7 +1059,7 @@ pub trait PrettyPrinter<'tcx>: fn pretty_print_dyn_existential( mut self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>, ) -> Result { // Generate the main trait ref, including associated types. let mut first = true; @@ -1763,7 +1763,7 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { fn print_dyn_existential( self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>, ) -> Result { self.pretty_print_dyn_existential(predicates) } @@ -2523,12 +2523,12 @@ pub struct PrintClosureAsImpl<'tcx> { forward_display_to_print! { ty::Region<'tcx>, Ty<'tcx>, - &'tcx ty::List>>, + &'tcx ty::List>, ty::Const<'tcx>, // HACK(eddyb) these are exhaustive instead of generic, // because `for<'tcx>` isn't possible yet. - ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>, + ty::PolyExistentialPredicate<'tcx>, ty::Binder<'tcx, ty::TraitRef<'tcx>>, ty::Binder<'tcx, ty::ExistentialTraitRef<'tcx>>, ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index c083a405e3c..5708abf0729 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -649,7 +649,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( if is_match { Ok(a) } else { Err(TypeError::ConstMismatch(expected_found(relation, a, b))) } } -impl<'tcx> Relate<'tcx> for &'tcx ty::List>> { +impl<'tcx> Relate<'tcx> for &'tcx ty::List> { fn relate>( relation: &mut R, a: Self, diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 9f0598d0ba8..6be8fdd7cd7 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -586,7 +586,7 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeSuperVisitable<'tcx> for ty::Binder<'tcx, } } -impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List>> { +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { fn try_fold_with>(self, folder: &mut F) -> Result { ty::util::fold_list(self, folder, |tcx, v| tcx.intern_poly_existential_predicates(v)) } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 49d82b503a4..e2a7b09de6a 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -703,7 +703,9 @@ impl<'tcx> ExistentialPredicate<'tcx> { } } -impl<'tcx> Binder<'tcx, ExistentialPredicate<'tcx>> { +pub type PolyExistentialPredicate<'tcx> = Binder<'tcx, ExistentialPredicate<'tcx>>; + +impl<'tcx> PolyExistentialPredicate<'tcx> { /// Given an existential predicate like `?Self: PartialEq` (e.g., derived from `dyn PartialEq`), /// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self` /// has been replaced with `self_ty` (e.g., `self_ty: PartialEq`, in our example). @@ -727,7 +729,7 @@ impl<'tcx> Binder<'tcx, ExistentialPredicate<'tcx>> { } } -impl<'tcx> List>> { +impl<'tcx> List> { /// Returns the "principal `DefId`" of this set of existential predicates. /// /// A Rust trait object type consists (in addition to a lifetime bound) diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 46c5fe78ffb..c60a2f4671d 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -244,7 +244,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolPrinter<'tcx> { fn print_dyn_existential( mut self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>, ) -> Result { let mut first = true; for p in predicates { diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 6aa031c8378..87128e0f893 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -12,8 +12,8 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; use rustc_middle::ty::{ - self, Binder, Const, ExistentialPredicate, FloatTy, FnSig, IntTy, List, Region, RegionKind, - TermKind, Ty, TyCtxt, UintTy, + self, Const, ExistentialPredicate, FloatTy, FnSig, IntTy, List, Region, RegionKind, TermKind, + Ty, TyCtxt, UintTy, }; use rustc_span::def_id::DefId; use rustc_span::symbol::sym; @@ -226,7 +226,7 @@ fn encode_fnsig<'tcx>( /// Rust types that are not used at the FFI boundary. fn encode_predicate<'tcx>( tcx: TyCtxt<'tcx>, - predicate: Binder<'tcx, ExistentialPredicate<'tcx>>, + predicate: ty::PolyExistentialPredicate<'tcx>, dict: &mut FxHashMap, usize>, options: EncodeTyOptions, ) -> String { @@ -261,13 +261,13 @@ fn encode_predicate<'tcx>( /// Rust types that are not used at the FFI boundary. fn encode_predicates<'tcx>( tcx: TyCtxt<'tcx>, - predicates: &List>>, + predicates: &List>, dict: &mut FxHashMap, usize>, options: EncodeTyOptions, ) -> String { // E as part of vendor extended type let mut s = String::new(); - let predicates: Vec>> = + let predicates: Vec> = predicates.iter().map(|predicate| predicate).collect(); for predicate in predicates { s.push_str(&encode_predicate(tcx, predicate, dict, options)); diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index e540e2f2a21..6ad0a7d2911 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -502,7 +502,7 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> { fn print_dyn_existential( mut self, - predicates: &'tcx ty::List>>, + predicates: &'tcx ty::List>, ) -> Result { // Okay, so this is a bit tricky. Imagine we have a trait object like // `dyn for<'a> Foo<'a, Bar = &'a ()>`. When we mangle this, the diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index d05e893de43..fce92c66ee8 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -758,7 +758,7 @@ impl<'tcx> WfPredicates<'tcx> { fn from_object_ty( &mut self, ty: Ty<'tcx>, - data: &'tcx ty::List>>, + data: &'tcx ty::List>, region: ty::Region<'tcx>, ) { // Imagine a type like this: @@ -822,7 +822,7 @@ impl<'tcx> WfPredicates<'tcx> { /// `infer::required_region_bounds`, see that for more information. pub fn object_region_bounds<'tcx>( tcx: TyCtxt<'tcx>, - existential_predicates: &'tcx ty::List>>, + existential_predicates: &'tcx ty::List>, ) -> Vec> { // Since we don't actually *know* the self type for an object, // this "open(err)" serves as a kind of dummy standin -- basically diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs index 25cedefa261..36bd466496e 100644 --- a/compiler/rustc_traits/src/chalk/lowering.rs +++ b/compiler/rustc_traits/src/chalk/lowering.rs @@ -634,7 +634,7 @@ impl<'tcx> LowerInto<'tcx, Option LowerInto<'tcx, chalk_ir::Binders>>> - for &'tcx ty::List>> + for &'tcx ty::List> { fn lower_into( self, diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs index c8c6f32c6c9..180d534636e 100644 --- a/src/tools/clippy/clippy_lints/src/ptr.rs +++ b/src/tools/clippy/clippy_lints/src/ptr.rs @@ -687,7 +687,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args: fn matches_preds<'tcx>( cx: &LateContext<'tcx>, ty: Ty<'tcx>, - preds: &'tcx [Binder<'tcx, ExistentialPredicate<'tcx>>], + preds: &'tcx [ty::PolyExistentialPredicate<'tcx>], ) -> bool { let infcx = cx.tcx.infer_ctxt().build(); preds.iter().all(|&p| match cx.tcx.erase_late_bound_regions(p) {