diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:44 +0000 |
commit | c23a457e72abe608715ac76f076f47dc42af07a5 (patch) | |
tree | 2772049aaf84b5c9d0ed12ec8d86812f7a7904b6 /compiler/rustc_ty_utils | |
parent | Releasing progress-linux version 1.73.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-c23a457e72abe608715ac76f076f47dc42af07a5.tar.xz rustc-c23a457e72abe608715ac76f076f47dc42af07a5.zip |
Merging upstream version 1.74.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_ty_utils')
-rw-r--r-- | compiler/rustc_ty_utils/src/abi.rs | 25 | ||||
-rw-r--r-- | compiler/rustc_ty_utils/src/implied_bounds.rs | 4 | ||||
-rw-r--r-- | compiler/rustc_ty_utils/src/instance.rs | 26 | ||||
-rw-r--r-- | compiler/rustc_ty_utils/src/layout.rs | 14 | ||||
-rw-r--r-- | compiler/rustc_ty_utils/src/needs_drop.rs | 58 | ||||
-rw-r--r-- | compiler/rustc_ty_utils/src/opaque_types.rs | 8 | ||||
-rw-r--r-- | compiler/rustc_ty_utils/src/ty.rs | 28 |
7 files changed, 89 insertions, 74 deletions
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 4d0b84753..16183403d 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -172,7 +172,10 @@ fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv { use rustc_target::spec::abi::Abi::*; match tcx.sess.target.adjust_abi(abi) { RustIntrinsic | PlatformIntrinsic | Rust | RustCall => Conv::Rust, - RustCold => Conv::RustCold, + + // This is intentionally not using `Conv::Cold`, as that has to preserve + // even SIMD registers, which is generally not a good trade-off. + RustCold => Conv::PreserveMost, // It's the ABI's job to select this, not ours. System { .. } => bug!("system abi should be selected elsewhere"), @@ -517,6 +520,8 @@ fn fn_abi_adjust_for_abi<'tcx>( _ => return, } + // `Aggregate` ABI must be adjusted to ensure that ABI-compatible Rust types are passed + // the same way. let size = arg.layout.size; if arg.layout.is_unsized() || size > Pointer(AddressSpace::DATA).size(cx) { @@ -583,19 +588,11 @@ fn make_thin_self_ptr<'tcx>( // To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we // get a built-in pointer type let mut fat_pointer_layout = layout; - 'descend_newtypes: while !fat_pointer_layout.ty.is_unsafe_ptr() - && !fat_pointer_layout.ty.is_ref() - { - for i in 0..fat_pointer_layout.fields.count() { - let field_layout = fat_pointer_layout.field(cx, i); - - if !field_layout.is_zst() { - fat_pointer_layout = field_layout; - continue 'descend_newtypes; - } - } - - bug!("receiver has no non-zero-sized fields {:?}", fat_pointer_layout); + while !fat_pointer_layout.ty.is_unsafe_ptr() && !fat_pointer_layout.ty.is_ref() { + fat_pointer_layout = fat_pointer_layout + .non_1zst_field(cx) + .expect("not exactly one non-1-ZST field in a `DispatchFromDyn` type") + .1 } fat_pointer_layout.ty diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 436f10a4f..ec2e0daaf 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -119,7 +119,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' }, DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)), DefKind::OpaqueTy => match tcx.def_kind(tcx.local_parent(def_id)) { - DefKind::TyAlias { .. } => ty::List::empty(), + DefKind::TyAlias => ty::List::empty(), DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)), // Nested opaque types only occur in associated types: // ` type Opaque<T> = impl Trait<&'static T, AssocTy = impl Nested>; ` @@ -136,7 +136,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' | DefKind::Enum | DefKind::Variant | DefKind::Trait - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::TyParam diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index e1a15b5cf..91f1c2131 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -55,6 +55,7 @@ fn resolve_instance<'tcx>( } } else { debug!(" => free item"); + // FIXME(effects): we may want to erase the effect param if that is present on this item. ty::InstanceDef::Item(def_id) }; @@ -140,11 +141,34 @@ fn resolve_associated_item<'tcx>( false } }; - if !eligible { return Ok(None); } + // HACK: We may have overlapping `dyn Trait` built-in impls and + // user-provided blanket impls. Detect that case here, and return + // ambiguity. + // + // This should not affect totally monomorphized contexts, only + // resolve calls that happen polymorphically, such as the mir-inliner + // and const-prop (and also some lints). + let self_ty = rcvr_args.type_at(0); + if !self_ty.is_known_rigid() { + let predicates = tcx + .predicates_of(impl_data.impl_def_id) + .instantiate(tcx, impl_data.args) + .predicates; + let sized_def_id = tcx.lang_items().sized_trait(); + // If we find a `Self: Sized` bound on the item, then we know + // that `dyn Trait` can certainly never apply here. + if !predicates.into_iter().filter_map(ty::Clause::as_trait_clause).any(|clause| { + Some(clause.def_id()) == sized_def_id + && clause.skip_binder().self_ty() == self_ty + }) { + return Ok(None); + } + } + // Any final impl is required to define all associated items. if !leaf_def.item.defaultness(tcx).has_value() { let guard = tcx.sess.delay_span_bug( diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 6b4273c03..5bd68d7cc 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -7,6 +7,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::layout::{ IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES, }; +use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ self, AdtDef, EarlyBinder, GenericArgsRef, ReprOptions, Ty, TyCtxt, TypeVisitableExt, }; @@ -35,6 +36,9 @@ fn layout_of<'tcx>( let (param_env, ty) = query.into_parts(); debug!(?ty); + // Optimization: We convert to RevealAll and convert opaque types in the where bounds + // to their hidden types. This reduces overall uncached invocations of `layout_of` and + // is thus a small performance improvement. let param_env = param_env.with_reveal_all_normalized(tcx); let unnormalized_ty = ty; @@ -192,7 +196,7 @@ fn layout_of_uncached<'tcx>( let metadata_layout = cx.layout_of(metadata_ty)?; // If the metadata is a 1-zst, then the pointer is thin. - if metadata_layout.is_zst() && metadata_layout.align.abi.bytes() == 1 { + if metadata_layout.is_1zst() { return Ok(tcx.mk_layout(LayoutS::scalar(cx, data_ptr))); } @@ -573,11 +577,7 @@ fn layout_of_uncached<'tcx>( return Err(error(cx, LayoutError::Unknown(ty))); } - ty::Bound(..) - | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) - | ty::Infer(_) - | ty::Error(_) => { + ty::Bound(..) | ty::GeneratorWitness(..) | ty::Infer(_) | ty::Error(_) => { bug!("Layout::compute: unexpected type `{}`", ty) } @@ -937,7 +937,7 @@ fn record_layout_for_printing_outlined<'tcx>( // (delay format until we actually need it) let record = |kind, packed, opt_discr_size, variants| { - let type_desc = format!("{:?}", layout.ty); + let type_desc = with_no_trimmed_paths!(format!("{}", layout.ty)); cx.tcx.sess.code_stats.record_type_size( kind, type_desc, diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 1fc5d9359..51a6d6235 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -7,7 +7,7 @@ use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop}; use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt}; use rustc_session::Limit; -use rustc_span::{sym, DUMMY_SP}; +use rustc_span::sym; use crate::errors::NeedsDropOverflow; @@ -66,6 +66,9 @@ fn has_significant_drop_raw<'tcx>( struct NeedsDropTypes<'tcx, F> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, + // Whether to reveal coroutine witnesses, this is set + // to `false` unless we compute `needs_drop` for a coroutine witness. + reveal_coroutine_witnesses: bool, query_ty: Ty<'tcx>, seen_tys: FxHashSet<Ty<'tcx>>, /// A stack of types left to process, and the recursion depth when we @@ -89,6 +92,7 @@ impl<'tcx, F> NeedsDropTypes<'tcx, F> { Self { tcx, param_env, + reveal_coroutine_witnesses: false, seen_tys, query_ty: ty, unchecked_tys: vec![(ty, 0)], @@ -133,8 +137,31 @@ where // The information required to determine whether a generator has drop is // computed on MIR, while this very method is used to build MIR. // To avoid cycles, we consider that generators always require drop. - ty::Generator(..) if tcx.sess.opts.unstable_opts.drop_tracking_mir => { - return Some(Err(AlwaysRequiresDrop)); + // + // HACK: Because we erase regions contained in the coroutine witness, we + // have to conservatively assume that every region captured by the + // coroutine has to be live when dropped. This results in a lot of + // undesirable borrowck errors. During borrowck, we call `needs_drop` + // for the coroutine witness and check whether any of the contained types + // need to be dropped, and only require the captured types to be live + // if they do. + ty::Generator(_, args, _) => { + if self.reveal_coroutine_witnesses { + queue_type(self, args.as_generator().witness()); + } else { + return Some(Err(AlwaysRequiresDrop)); + } + } + ty::GeneratorWitness(def_id, args) => { + if let Some(witness) = tcx.mir_generator_witnesses(def_id) { + self.reveal_coroutine_witnesses = true; + for field_ty in &witness.field_tys { + queue_type( + self, + EarlyBinder::bind(field_ty.ty).instantiate(tcx, args), + ); + } + } } _ if component.is_copy_modulo_regions(tcx, self.param_env) => (), @@ -145,29 +172,6 @@ where } } - ty::Generator(def_id, args, _) => { - let args = args.as_generator(); - for upvar in args.upvar_tys() { - queue_type(self, upvar); - } - - let witness = args.witness(); - let interior_tys = match witness.kind() { - &ty::GeneratorWitness(tys) => tcx.erase_late_bound_regions(tys), - _ => { - tcx.sess.delay_span_bug( - tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP), - format!("unexpected generator witness type {witness:?}"), - ); - return Some(Err(AlwaysRequiresDrop)); - } - }; - - for interior_ty in interior_tys { - queue_type(self, interior_ty); - } - } - // Check for a `Drop` impl and whether this is a union or // `ManuallyDrop`. If it's a struct or enum without a `Drop` // impl then check whether the field types need `Drop`. @@ -214,8 +218,6 @@ where | ty::FnPtr(..) | ty::Tuple(_) | ty::Bound(..) - | ty::GeneratorWitness(..) - | ty::GeneratorWitnessMIR(..) | ty::Never | ty::Infer(_) | ty::Error(_) => { diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 38768f0a0..06a30677d 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -53,9 +53,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { fn parent(&self) -> Option<LocalDefId> { match self.tcx.def_kind(self.item) { - DefKind::AnonConst | DefKind::InlineConst | DefKind::Fn | DefKind::TyAlias { .. } => { - None - } + DefKind::AnonConst | DefKind::InlineConst | DefKind::Fn | DefKind::TyAlias => None, DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => { Some(self.tcx.local_parent(self.item)) } @@ -118,7 +116,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { #[instrument(level = "trace", skip(self))] fn visit_nested_item(&mut self, id: rustc_hir::ItemId) { let id = id.owner_id.def_id; - if let DefKind::TyAlias { .. } = self.collector.tcx.def_kind(id) { + if let DefKind::TyAlias = self.collector.tcx.def_kind(id) { let items = self.collector.tcx.opaque_types_defined_by(id); self.collector.opaques.extend(items); } @@ -297,7 +295,7 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [ collector.collect_body_and_predicate_taits(); } // We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds` - DefKind::TyAlias { .. } | DefKind::AssocTy => { + DefKind::TyAlias | DefKind::AssocTy => { tcx.type_of(item).instantiate_identity().visit_with(&mut collector); } DefKind::OpaqueTy => { diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index ba0258b63..4234e69e8 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -4,7 +4,7 @@ use rustc_hir::def::DefKind; use rustc_index::bit_set::BitSet; use rustc_middle::query::Providers; use rustc_middle::ty::{ - self, EarlyBinder, ToPredicate, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, + self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, }; use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_span::DUMMY_SP; @@ -21,13 +21,7 @@ fn sized_constraint_for_ty<'tcx>( Bool | Char | Int(..) | Uint(..) | Float(..) | RawPtr(..) | Ref(..) | FnDef(..) | FnPtr(_) | Array(..) | Closure(..) | Generator(..) | Never => vec![], - Str - | Dynamic(..) - | Slice(_) - | Foreign(..) - | Error(_) - | GeneratorWitness(..) - | GeneratorWitnessMIR(..) => { + Str | Dynamic(..) | Slice(_) | Foreign(..) | Error(_) | GeneratorWitness(..) => { // these are never sized - return the target type vec![ty] } @@ -220,13 +214,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> { // strategy, then just reinterpret the associated type like an opaque :^) let default_ty = self.tcx.type_of(shifted_alias_ty.def_id).instantiate(self.tcx, shifted_alias_ty.args); - self.predicates.push( - ty::Binder::bind_with_vars( - ty::ProjectionPredicate { projection_ty: shifted_alias_ty, term: default_ty.into() }, - self.bound_vars, - ) - .to_predicate(self.tcx), - ); + self.predicates.push(ty::Clause::from_projection_clause(self.tcx, ty::Binder::bind_with_vars( + ty::ProjectionPredicate { projection_ty: shifted_alias_ty, term: default_ty.into() }, + self.bound_vars, + ))); // We walk the *un-shifted* alias ty, because we're tracking the de bruijn // binder depth, and if we were to walk `shifted_alias_ty` instead, we'd @@ -299,9 +290,12 @@ fn issue33140_self_ty(tcx: TyCtxt<'_>, def_id: DefId) -> Option<EarlyBinder<Ty<' } /// Check if a function is async. -fn asyncness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::IsAsync { +fn asyncness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Asyncness { let node = tcx.hir().get_by_def_id(def_id); - node.fn_sig().map_or(hir::IsAsync::NotAsync, |sig| sig.header.asyncness) + node.fn_sig().map_or(ty::Asyncness::No, |sig| match sig.header.asyncness { + hir::IsAsync::Async(_) => ty::Asyncness::Yes, + hir::IsAsync::NotAsync => ty::Asyncness::No, + }) } fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet<u32> { |