From f4652226f92307a1f6e8fd8cad41bd93da6e1739 Mon Sep 17 00:00:00 2001 From: Lukas Markeffsky <@> Date: Thu, 28 Mar 2024 14:59:03 +0100 Subject: [PATCH] skip known panics lint for impossible items --- compiler/rustc_middle/src/query/mod.rs | 7 +++ .../src/known_panics_lint.rs | 5 +++ .../rustc_trait_selection/src/traits/mod.rs | 25 +++++++++++ .../lint/known-panics-impossible-pred-ice.rs | 43 +++++++++++++++++++ 4 files changed, 80 insertions(+) create mode 100644 tests/ui/mir/lint/known-panics-impossible-pred-ice.rs diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 5e4454db3e28f..057c1ee2229e9 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2116,6 +2116,13 @@ rustc_queries! { } } + query is_impossible_item(def_id: DefId) -> bool { + desc { |tcx| + "checking if `{}` has predicates that are impossible to satisfy", + tcx.def_path_str(def_id), + } + } + query is_impossible_associated_item(key: (DefId, DefId)) -> bool { desc { |tcx| "checking if `{}` is impossible to reference within `{}`", diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index a20958e74dffe..c65113e1b5a64 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -51,6 +51,11 @@ impl<'tcx> MirLint<'tcx> for KnownPanicsLint { return; } + if tcx.is_impossible_item(def_id) { + trace!("KnownPanicsLint skipped for impossible item {:?}", def_id); + return; + } + trace!("KnownPanicsLint starting for {:?}", def_id); let mut linter = ConstPropagator::new(body, tcx); diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index c875d3da47e5f..892f04f2a3007 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -421,6 +421,30 @@ fn instantiate_and_check_impossible_predicates<'tcx>( result } +/// Checks whether an item is impossible to reference. +#[instrument(level = "debug", skip(tcx), ret)] +fn is_impossible_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { + let item_param_env = tcx.param_env(def_id); + let predicates = tcx + .predicates_of(def_id) + .predicates + .iter() + .filter_map(|&(clause, _)| tcx.try_normalize_erasing_regions(item_param_env, clause).ok()) + .filter(|clause| clause.is_global()); + + let global_param_env = ty::ParamEnv::reveal_all(); + let infcx = tcx.infer_ctxt().build(); + let ocx = ObligationCtxt::new(&infcx); + for predicate in predicates { + let obligation = + Obligation::new(tcx, ObligationCause::dummy(), global_param_env, predicate); + ocx.register_obligation(obligation); + } + + let errors = ocx.select_all_or_error(); + !errors.is_empty() +} + /// Checks whether a trait's associated item is impossible to reference on a given impl. /// /// This only considers predicates that reference the impl's generics, and not @@ -506,6 +530,7 @@ pub fn provide(providers: &mut Providers) { specializes: specialize::specializes, instantiate_and_check_impossible_predicates, check_tys_might_be_eq: misc::check_tys_might_be_eq, + is_impossible_item, is_impossible_associated_item, ..*providers }; diff --git a/tests/ui/mir/lint/known-panics-impossible-pred-ice.rs b/tests/ui/mir/lint/known-panics-impossible-pred-ice.rs new file mode 100644 index 0000000000000..b831a51b8e7d0 --- /dev/null +++ b/tests/ui/mir/lint/known-panics-impossible-pred-ice.rs @@ -0,0 +1,43 @@ +//@ build-pass +// Regression test for an ICE: https://github.com/rust-lang/rust/issues/123134 + +trait Api: Sized { + type Device: ?Sized; +} + +struct OpenDevice +where + A::Device: Sized, +{ + device: A::Device, + queue: (), +} + +trait Adapter { + type A: Api; + + fn open() -> OpenDevice + where + ::Device: Sized; +} + +struct ApiS; + +impl Api for ApiS { + type Device = [u8]; +} + +impl Adapter for T +{ + type A = ApiS; + + // This function has the impossible predicate `[u8]: Sized`. + fn open() -> OpenDevice + where + ::Device: Sized, + { + unreachable!() + } +} + +fn main() {}