Skip to content

Commit

Permalink
normalizes-to: handle negative impls
Browse files Browse the repository at this point in the history
  • Loading branch information
lcnr committed Mar 1, 2024
1 parent b0696a5 commit 0700ec0
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 3 deletions.
19 changes: 16 additions & 3 deletions compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,28 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
let tcx = ecx.tcx();

let goal_trait_ref = goal.predicate.alias.trait_ref(tcx);
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
let impl_trait_header = tcx.impl_trait_header(impl_def_id).unwrap();
let drcx = DeepRejectCtxt { treat_obligation_params: TreatParams::ForLookup };
if !drcx.args_may_unify(goal_trait_ref.args, impl_trait_ref.skip_binder().args) {
if !drcx.args_may_unify(
goal.predicate.trait_ref(tcx).args,
impl_trait_header.skip_binder().trait_ref.args,
) {
return Err(NoSolution);
}

// We have to ignore negative impls when projecting.
let impl_polarity = impl_trait_header.skip_binder().polarity;
match impl_polarity {
ty::ImplPolarity::Negative => return Err(NoSolution),
ty::ImplPolarity::Reservation => {
unimplemented!("reservation impl for trait with assoc item: {:?}", goal)
}
ty::ImplPolarity::Positive => {}
};

ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
let impl_args = ecx.fresh_args_for_item(impl_def_id);
let impl_trait_ref = impl_trait_ref.instantiate(tcx, impl_args);
let impl_trait_ref = impl_trait_header.instantiate(tcx, impl_args).trait_ref;

ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;

Expand Down
22 changes: 22 additions & 0 deletions tests/ui/traits/negative-impls/negative-impl-normalizes-to.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//@ revisions: current next
//@[next] compile-flags: -Znext-solver
//@ check-pass

// Check that negative impls for traits with associated types
// do not result in an ICE when trying to normalize.
#![feature(negative_impls)]
trait Trait {
type Assoc;
}

struct Local<T>(T);
impl !Trait for Local<u32> {}
impl Trait for Local<i32> {
type Assoc = i32;
}

trait NoOverlap {}
impl<T: Trait<Assoc = u32>> NoOverlap for T {}
impl<T> NoOverlap for Local<T> {}

fn main() {}

0 comments on commit 0700ec0

Please sign in to comment.