diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_arena/src/lib.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_borrowck/src/region_infer/opaque_types.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/lib.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/check.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs | 21 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs | 53 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 24 | ||||
| -rw-r--r-- | compiler/rustc_hir_typeck/src/writeback.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/mod.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_mir_transform/src/impossible_predicates.rs | 56 | ||||
| -rw-r--r-- | compiler/rustc_mir_transform/src/instsimplify.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_mir_transform/src/lib.rs | 49 | ||||
| -rw-r--r-- | compiler/rustc_mir_transform/src/remove_zsts.rs | 42 |
13 files changed, 161 insertions, 129 deletions
diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 4d8525989cc..b21ccba93bb 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -78,7 +78,7 @@ impl<T> ArenaChunk<T> { // been initialized. unsafe { let slice = self.storage.as_mut(); - ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(&mut slice[..len])); + slice[..len].assume_init_drop(); } } } diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 3e16a3ca157..7c484327e31 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -152,7 +152,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { let (Ok(e) | Err(e)) = prev .build_mismatch_error( &OpaqueHiddenType { ty, span: concrete_type.span }, - opaque_type_key.def_id, infcx.tcx, ) .map(|d| d.emit()); diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 58fe3ec4b85..cc5eb9c335e 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -566,9 +566,7 @@ pub enum StashKey { /// FRU syntax MaybeFruTypo, CallAssocMethod, - TraitMissingMethod, AssociatedTypeSuggestion, - OpaqueHiddenTypeMismatch, MaybeForgetReturn, /// Query cycle detected, stashing in favor of a better error. Cycle, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 821829455d9..974a8648bc0 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -575,7 +575,7 @@ fn sanity_check_found_hidden_type<'tcx>( } else { let span = tcx.def_span(key.def_id); let other = ty::OpaqueHiddenType { ty: hidden_ty, span }; - Err(ty.build_mismatch_error(&other, key.def_id, tcx)?.emit()) + Err(ty.build_mismatch_error(&other, tcx)?.emit()) } } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index c933095fd3d..d1a1e36c1d5 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -1,4 +1,3 @@ -use rustc_errors::StashKey; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; @@ -45,7 +44,7 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type( if !hidden.ty.references_error() { for concrete_type in locator.typeck_types { if concrete_type.ty != tcx.erase_regions(hidden.ty) { - if let Ok(d) = hidden.build_mismatch_error(&concrete_type, def_id, tcx) { + if let Ok(d) = hidden.build_mismatch_error(&concrete_type, tcx) { d.emit(); } } @@ -121,7 +120,7 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local if !hidden.ty.references_error() { for concrete_type in locator.typeck_types { if concrete_type.ty != tcx.erase_regions(hidden.ty) { - if let Ok(d) = hidden.build_mismatch_error(&concrete_type, def_id, tcx) { + if let Ok(d) = hidden.build_mismatch_error(&concrete_type, tcx) { d.emit(); } } @@ -285,9 +284,8 @@ impl TaitConstraintLocator<'_> { debug!(?concrete_type, "found constraint"); if let Some(prev) = &mut self.found { if concrete_type.ty != prev.ty { - let (Ok(guar) | Err(guar)) = prev - .build_mismatch_error(&concrete_type, self.def_id, self.tcx) - .map(|d| d.emit()); + let (Ok(guar) | Err(guar)) = + prev.build_mismatch_error(&concrete_type, self.tcx).map(|d| d.emit()); prev.ty = Ty::new_error(self.tcx, guar); } } else { @@ -361,11 +359,8 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>( ); if let Some(prev) = &mut hir_opaque_ty { if concrete_type.ty != prev.ty { - if let Ok(d) = prev.build_mismatch_error(&concrete_type, def_id, tcx) { - d.stash( - tcx.def_span(opaque_type_key.def_id), - StashKey::OpaqueHiddenTypeMismatch, - ); + if let Ok(d) = prev.build_mismatch_error(&concrete_type, tcx) { + d.emit(); } } } else { @@ -435,9 +430,7 @@ impl RpitConstraintChecker<'_> { debug!(?concrete_type, "found constraint"); if concrete_type.ty != self.found.ty { - if let Ok(d) = - self.found.build_mismatch_error(&concrete_type, self.def_id, self.tcx) - { + if let Ok(d) = self.found.build_mismatch_error(&concrete_type, self.tcx) { d.emit(); } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index b7d3617fbe7..a1f2b8c7594 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -2,10 +2,12 @@ use rustc_ast::TraitObjectSyntax; use rustc_errors::codes::*; use rustc_errors::{Diag, EmissionGuarantee, ErrorGuaranteed, StashKey, Suggestions}; use rustc_hir as hir; -use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def::{DefKind, Namespace, Res}; +use rustc_hir::def_id::DefId; use rustc_lint_defs::Applicability; use rustc_lint_defs::builtin::BARE_TRAIT_OBJECTS; use rustc_span::Span; +use rustc_span::edit_distance::find_best_match_for_name; use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName; use super::HirTyLowerer; @@ -86,7 +88,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Check if the impl trait that we are considering is an impl of a local trait. self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag); self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag); - // In case there is an associate type with the same name + self.maybe_suggest_typoed_method( + self_ty, + poly_trait_ref.trait_ref.trait_def_id(), + &mut diag, + ); + // In case there is an associated type with the same name // Add the suggestion to this error if let Some(mut sugg) = tcx.dcx().steal_non_err(self_ty.span, StashKey::AssociatedTypeSuggestion) @@ -96,7 +103,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { s1.append(s2); sugg.cancel(); } - diag.stash(self_ty.span, StashKey::TraitMissingMethod) + Some(diag.emit()) } else { tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| { lint.primary_message("trait objects without an explicit `dyn` are deprecated"); @@ -343,4 +350,44 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); } } + + fn maybe_suggest_typoed_method( + &self, + self_ty: &hir::Ty<'_>, + trait_def_id: Option<DefId>, + diag: &mut Diag<'_>, + ) { + let tcx = self.tcx(); + let Some(trait_def_id) = trait_def_id else { + return; + }; + let hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Path(hir::QPath::TypeRelative(path_ty, segment)), + .. + }) = tcx.parent_hir_node(self_ty.hir_id) + else { + return; + }; + if path_ty.hir_id != self_ty.hir_id { + return; + } + let names: Vec<_> = tcx + .associated_items(trait_def_id) + .in_definition_order() + .filter(|assoc| assoc.kind.namespace() == Namespace::ValueNS) + .map(|cand| cand.name) + .collect(); + if let Some(typo) = find_best_match_for_name(&names, segment.ident.name, None) { + diag.span_suggestion_verbose( + segment.ident.span, + format!( + "you may have misspelled this associated item, causing `{}` \ + to be interpreted as a type rather than a trait", + tcx.item_name(trait_def_id), + ), + typo, + Applicability::MaybeIncorrect, + ); + } + } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 4130f0c11dd..be6d9570e35 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -3,7 +3,7 @@ use std::slice; use rustc_abi::FieldIdx; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey}; +use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan}; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; @@ -806,17 +806,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let item_name = item_segment.ident; let result = self .resolve_fully_qualified_call(span, item_name, ty.normalized, qself.span, hir_id) - .map(|r| { - // lint bare trait if the method is found in the trait - if span.edition().at_least_rust_2021() { - self.dcx().try_steal_modify_and_emit_err( - qself.span, - StashKey::TraitMissingMethod, - |_err| {}, - ); - } - r - }) .or_else(|error| { let guar = self .dcx() @@ -840,17 +829,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - // Emit the diagnostic for bare traits. (We used to cancel for slightly better - // error messages, but cancelling stashed diagnostics is no longer allowed because - // it causes problems when tracking whether errors have actually occurred.) - if span.edition().at_least_rust_2021() { - self.dcx().try_steal_modify_and_emit_err( - qself.span, - StashKey::TraitMissingMethod, - |_err| {}, - ); - } - if item_name.name != kw::Empty { self.report_method_error( hir_id, diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index f63a0b17964..7c5838db586 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -5,7 +5,7 @@ use std::mem; use rustc_data_structures::unord::ExtendUnord; -use rustc_errors::{ErrorGuaranteed, StashKey}; +use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::HirId; use rustc_hir::intravisit::{self, Visitor}; @@ -582,15 +582,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { && last_opaque_ty.ty != hidden_type.ty { assert!(!self.fcx.next_trait_solver()); - if let Ok(d) = hidden_type.build_mismatch_error( - &last_opaque_ty, - opaque_type_key.def_id, - self.tcx(), - ) { - d.stash( - self.tcx().def_span(opaque_type_key.def_id), - StashKey::OpaqueHiddenTypeMismatch, - ); + if let Ok(d) = hidden_type.build_mismatch_error(&last_opaque_ty, self.tcx()) { + d.emit(); } } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 2d69386176b..bf0ccdc0f10 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -32,7 +32,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; -use rustc_errors::{Diag, ErrorGuaranteed, StashKey}; +use rustc_errors::{Diag, ErrorGuaranteed}; use rustc_hir::LangItem; use rustc_hir::def::{CtorKind, CtorOf, DefKind, DocLinkResMap, LifetimeRes, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LocalDefIdMap}; @@ -782,18 +782,8 @@ impl<'tcx> OpaqueHiddenType<'tcx> { pub fn build_mismatch_error( &self, other: &Self, - opaque_def_id: LocalDefId, tcx: TyCtxt<'tcx>, ) -> Result<Diag<'tcx>, ErrorGuaranteed> { - // We used to cancel here for slightly better error messages, but - // cancelling stashed diagnostics is no longer allowed because it - // causes problems when tracking whether errors have actually - // occurred. - tcx.sess.dcx().try_steal_modify_and_emit_err( - tcx.def_span(opaque_def_id), - StashKey::OpaqueHiddenTypeMismatch, - |_err| {}, - ); (self.ty, other.ty).error_reported()?; // Found different concrete types for the opaque type. let sub_diag = if self.span == other.span { diff --git a/compiler/rustc_mir_transform/src/impossible_predicates.rs b/compiler/rustc_mir_transform/src/impossible_predicates.rs new file mode 100644 index 00000000000..ba8389bbe2f --- /dev/null +++ b/compiler/rustc_mir_transform/src/impossible_predicates.rs @@ -0,0 +1,56 @@ +//! Check if it's even possible to satisfy the 'where' clauses +//! for this item. +//! +//! It's possible to `#!feature(trivial_bounds)]` to write +//! a function with impossible to satisfy clauses, e.g.: +//! `fn foo() where String: Copy {}`. +//! +//! We don't usually need to worry about this kind of case, +//! since we would get a compilation error if the user tried +//! to call it. However, since we optimize even without any +//! calls to the function, we need to make sure that it even +//! makes sense to try to evaluate the body. +//! +//! If there are unsatisfiable where clauses, then all bets are +//! off, and we just give up. +//! +//! We manually filter the predicates, skipping anything that's not +//! "global". We are in a potentially generic context +//! (e.g. we are evaluating a function without instantiating generic +//! parameters, so this filtering serves two purposes: +//! +//! 1. We skip evaluating any predicates that we would +//! never be able prove are unsatisfiable (e.g. `<T as Foo>` +//! 2. We avoid trying to normalize predicates involving generic +//! parameters (e.g. `<T as Foo>::MyItem`). This can confuse +//! the normalization code (leading to cycle errors), since +//! it's usually never invoked in this way. + +use rustc_middle::mir::{Body, START_BLOCK, TerminatorKind}; +use rustc_middle::ty::{TyCtxt, TypeVisitableExt}; +use rustc_trait_selection::traits; +use tracing::trace; + +use crate::pass_manager::MirPass; + +pub(crate) struct ImpossiblePredicates; + +impl<'tcx> MirPass<'tcx> for ImpossiblePredicates { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let predicates = tcx + .predicates_of(body.source.def_id()) + .predicates + .iter() + .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); + if traits::impossible_predicates(tcx, traits::elaborate(tcx, predicates).collect()) { + trace!("found unsatisfiable predicates for {:?}", body.source); + // Clear the body to only contain a single `unreachable` statement. + let bbs = body.basic_blocks.as_mut(); + bbs.raw.truncate(1); + bbs[START_BLOCK].statements.clear(); + bbs[START_BLOCK].terminator_mut().kind = TerminatorKind::Unreachable; + body.var_debug_info.clear(); + body.local_decls.raw.truncate(body.arg_count + 1); + } + } +} diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index f74a577c598..20e2e3e8ba2 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -49,6 +49,7 @@ impl<'tcx> crate::MirPass<'tcx> for InstSimplify { ctx.simplify_ptr_aggregate(rvalue); ctx.simplify_cast(rvalue); ctx.simplify_repeated_aggregate(rvalue); + ctx.simplify_repeat_once(rvalue); } _ => {} } @@ -207,6 +208,18 @@ impl<'tcx> InstSimplifyContext<'_, 'tcx> { } } + /// Simplify `[x; 1]` to just `[x]`. + fn simplify_repeat_once(&self, rvalue: &mut Rvalue<'tcx>) { + if let Rvalue::Repeat(operand, count) = rvalue + && let Some(1) = count.try_to_target_usize(self.tcx) + { + *rvalue = Rvalue::Aggregate( + Box::new(AggregateKind::Array(operand.ty(self.local_decls, self.tcx))), + [operand.clone()].into(), + ); + } + } + fn simplify_primitive_clone( &self, terminator: &mut Terminator<'tcx>, diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 350929ffaa5..9459ef99445 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -34,8 +34,7 @@ use rustc_middle::util::Providers; use rustc_middle::{bug, query, span_bug}; use rustc_span::source_map::Spanned; use rustc_span::{DUMMY_SP, sym}; -use rustc_trait_selection::traits; -use tracing::{debug, trace}; +use tracing::debug; #[macro_use] mod pass_manager; @@ -142,6 +141,7 @@ declare_passes! { // Made public so that `mir_drops_elaborated_and_const_checked` can be overridden // by custom rustc drivers, running all the steps by themselves. See #114628. pub mod inline : Inline, ForceInline; + mod impossible_predicates : ImpossiblePredicates; mod instsimplify : InstSimplify { BeforeInline, AfterSimplifyCfg }; mod jump_threading : JumpThreading; mod known_panics_lint : KnownPanicsLint; @@ -502,50 +502,6 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & body.tainted_by_errors = Some(error_reported); } - // Check if it's even possible to satisfy the 'where' clauses - // for this item. - // - // This branch will never be taken for any normal function. - // However, it's possible to `#!feature(trivial_bounds)]` to write - // a function with impossible to satisfy clauses, e.g.: - // `fn foo() where String: Copy {}` - // - // We don't usually need to worry about this kind of case, - // since we would get a compilation error if the user tried - // to call it. However, since we optimize even without any - // calls to the function, we need to make sure that it even - // makes sense to try to evaluate the body. - // - // If there are unsatisfiable where clauses, then all bets are - // off, and we just give up. - // - // We manually filter the predicates, skipping anything that's not - // "global". We are in a potentially generic context - // (e.g. we are evaluating a function without instantiating generic - // parameters, so this filtering serves two purposes: - // - // 1. We skip evaluating any predicates that we would - // never be able prove are unsatisfiable (e.g. `<T as Foo>` - // 2. We avoid trying to normalize predicates involving generic - // parameters (e.g. `<T as Foo>::MyItem`). This can confuse - // the normalization code (leading to cycle errors), since - // it's usually never invoked in this way. - let predicates = tcx - .predicates_of(body.source.def_id()) - .predicates - .iter() - .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); - if traits::impossible_predicates(tcx, traits::elaborate(tcx, predicates).collect()) { - trace!("found unsatisfiable predicates for {:?}", body.source); - // Clear the body to only contain a single `unreachable` statement. - let bbs = body.basic_blocks.as_mut(); - bbs.raw.truncate(1); - bbs[START_BLOCK].statements.clear(); - bbs[START_BLOCK].terminator_mut().kind = TerminatorKind::Unreachable; - body.var_debug_info.clear(); - body.local_decls.raw.truncate(body.arg_count + 1); - } - run_analysis_to_runtime_passes(tcx, &mut body); // Now that drop elaboration has been performed, we can check for @@ -593,6 +549,7 @@ pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<' /// After this series of passes, no lifetime analysis based on borrowing can be done. fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let passes: &[&dyn MirPass<'tcx>] = &[ + &impossible_predicates::ImpossiblePredicates, &cleanup_post_borrowck::CleanupPostBorrowck, &remove_noop_landing_pads::RemoveNoopLandingPads, &simplify::SimplifyCfg::PostAnalysis, diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 64e183bcbc0..55e5701bd0a 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -36,31 +36,39 @@ struct Replacer<'a, 'tcx> { } /// A cheap, approximate check to avoid unnecessary `layout_of` calls. -fn maybe_zst(ty: Ty<'_>) -> bool { +/// +/// `Some(true)` is definitely ZST; `Some(false)` is definitely *not* ZST. +/// +/// `None` may or may not be, and must check `layout_of` to be sure. +fn trivially_zst<'tcx>(ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Option<bool> { match ty.kind() { - // maybe ZST (could be more precise) - ty::Adt(..) - | ty::Array(..) - | ty::Closure(..) - | ty::CoroutineClosure(..) - | ty::Tuple(..) - | ty::Alias(ty::Opaque, ..) => true, // definitely ZST - ty::FnDef(..) | ty::Never => true, - // unreachable or can't be ZST - _ => false, + ty::FnDef(..) | ty::Never => Some(true), + ty::Tuple(fields) if fields.is_empty() => Some(true), + ty::Array(_ty, len) if let Some(0) = len.try_to_target_usize(tcx) => Some(true), + // clearly not ZST + ty::Bool + | ty::Char + | ty::Int(..) + | ty::Uint(..) + | ty::Float(..) + | ty::RawPtr(..) + | ty::Ref(..) + | ty::FnPtr(..) => Some(false), + // check `layout_of` to see (including unreachable things we won't actually see) + _ => None, } } impl<'tcx> Replacer<'_, 'tcx> { fn known_to_be_zst(&self, ty: Ty<'tcx>) -> bool { - if !maybe_zst(ty) { - return false; + if let Some(is_zst) = trivially_zst(ty, self.tcx) { + is_zst + } else { + self.tcx + .layout_of(self.typing_env.as_query_input(ty)) + .is_ok_and(|layout| layout.is_zst()) } - let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(ty)) else { - return false; - }; - layout.is_zst() } fn make_zst(&self, ty: Ty<'tcx>) -> ConstOperand<'tcx> { |
