diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index 3aba5c85abc3a..248985715c267 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -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)?; diff --git a/tests/ui/traits/negative-impls/negative-impl-normalizes-to.rs b/tests/ui/traits/negative-impls/negative-impl-normalizes-to.rs new file mode 100644 index 0000000000000..998b0d0c458a4 --- /dev/null +++ b/tests/ui/traits/negative-impls/negative-impl-normalizes-to.rs @@ -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); +impl !Trait for Local {} +impl Trait for Local { + type Assoc = i32; +} + +trait NoOverlap {} +impl> NoOverlap for T {} +impl NoOverlap for Local {} + +fn main() {}