Skip to content

Commit

Permalink
skip known panics lint for impossible items
Browse files Browse the repository at this point in the history
  • Loading branch information
Lukas Markeffsky committed Mar 28, 2024
1 parent 551abd6 commit f465222
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 0 deletions.
7 changes: 7 additions & 0 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 `{}`",
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_mir_transform/src/known_panics_lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
25 changes: 25 additions & 0 deletions compiler/rustc_trait_selection/src/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
};
Expand Down
43 changes: 43 additions & 0 deletions tests/ui/mir/lint/known-panics-impossible-pred-ice.rs
Original file line number Diff line number Diff line change
@@ -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<A: Api>
where
A::Device: Sized,
{
device: A::Device,
queue: (),
}

trait Adapter {
type A: Api;

fn open() -> OpenDevice<Self::A>
where
<Self::A as Api>::Device: Sized;
}

struct ApiS;

impl Api for ApiS {
type Device = [u8];
}

impl<T> Adapter for T
{
type A = ApiS;

// This function has the impossible predicate `[u8]: Sized`.
fn open() -> OpenDevice<Self::A>
where
<Self::A as Api>::Device: Sized,
{
unreachable!()
}
}

fn main() {}

0 comments on commit f465222

Please sign in to comment.