summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_ty_utils
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
commitc23a457e72abe608715ac76f076f47dc42af07a5 (patch)
tree2772049aaf84b5c9d0ed12ec8d86812f7a7904b6 /compiler/rustc_ty_utils
parentReleasing progress-linux version 1.73.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-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.rs25
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs4
-rw-r--r--compiler/rustc_ty_utils/src/instance.rs26
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs14
-rw-r--r--compiler/rustc_ty_utils/src/needs_drop.rs58
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs8
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs28
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> {