diff options
Diffstat (limited to 'compiler/rustc_trait_selection/src')
3 files changed, 24 insertions, 0 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 08220c4fe9f..3e9e497672a 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -530,6 +530,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { associated_ty: Option<(&'static str, Ty<'tcx>)>, mut body_id: LocalDefId, ) { + if trait_pred.skip_binder().polarity == ty::ImplPolarity::Negative { + return; + } + let trait_pred = self.resolve_numeric_literals_with_default(trait_pred); let self_ty = trait_pred.skip_binder().self_ty(); diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 1db9b8ce92e..a8864f47ef0 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -57,6 +57,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if obligation.polarity() == ty::ImplPolarity::Negative { self.assemble_candidates_for_trait_alias(obligation, &mut candidates); self.assemble_candidates_from_impls(obligation, &mut candidates); + self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?; } else { self.assemble_candidates_for_trait_alias(obligation, &mut candidates); @@ -187,6 +188,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // Keep only those bounds which may apply, and propagate overflow if it occurs. for bound in matching_bounds { + if bound.skip_binder().polarity != stack.obligation.predicate.skip_binder().polarity { + continue; + } + // FIXME(oli-obk): it is suspicious that we are dropping the constness and // polarity here. let wc = self.where_clause_may_apply(stack, bound.map_bound(|t| t.trait_ref))?; diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 40e19abc0d0..0590e02d84a 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -328,6 +328,13 @@ impl<'tcx> WfPredicates<'tcx> { let tcx = self.tcx; let trait_ref = &trait_pred.trait_ref; + // Negative trait predicates don't require supertraits to hold, just + // that their substs are WF. + if trait_pred.polarity == ty::ImplPolarity::Negative { + self.compute_negative_trait_pred(trait_ref); + return; + } + // if the trait predicate is not const, the wf obligations should not be const as well. let obligations = if trait_pred.constness == ty::BoundConstness::NotConst { self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.substs) @@ -393,6 +400,14 @@ impl<'tcx> WfPredicates<'tcx> { ); } + // Compute the obligations that are required for `trait_ref` to be WF, + // given that it is a *negative* trait predicate. + fn compute_negative_trait_pred(&mut self, trait_ref: &ty::TraitRef<'tcx>) { + for arg in trait_ref.substs { + self.compute(arg); + } + } + /// Pushes the obligations required for `trait_ref::Item` to be WF /// into `self.out`. fn compute_projection(&mut self, data: ty::AliasTy<'tcx>) { |
