diff options
| author | Michael Goulet <michael@errs.io> | 2023-04-25 06:37:24 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2023-05-02 22:36:25 +0000 |
| commit | 03469c3f2e5f7318b9dd47483f5656b321880408 (patch) | |
| tree | 4def76c66dbe513023cae219c41de91c5043fcef /compiler | |
| parent | 40a63cb06ff21d7cd38f35c92a29162e43f9aadf (diff) | |
| download | rust-03469c3f2e5f7318b9dd47483f5656b321880408.tar.gz rust-03469c3f2e5f7318b9dd47483f5656b321880408.zip | |
Make negative trait bounds work with the old trait solver
Diffstat (limited to 'compiler')
4 files changed, 34 insertions, 0 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index fda59d000ea..1f01ad009dc 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -701,6 +701,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut dup_bindings = FxHashMap::default(); for binding in &assoc_bindings { + // Don't register additional associated type bounds for negative bounds, + // since we should have emitten an error for them earlier, and they will + // not be well-formed! + if polarity == ty::ImplPolarity::Negative { + self.tcx() + .sess + .delay_span_bug(binding.span, "negative trait bounds should not have bindings"); + continue; + } + // Specify type to assert that error was already reported in `Err` case. let _: Result<_, ErrorGuaranteed> = self.add_predicates_for_ast_type_binding( hir_id, diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index ef01d5d513b..f54e5e5e56f 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -200,6 +200,10 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { let bound_predicate = elaboratable.predicate().kind(); match bound_predicate.skip_binder() { ty::PredicateKind::Clause(ty::Clause::Trait(data)) => { + // Negative trait bounds do not imply any supertrait bounds + if data.polarity == ty::ImplPolarity::Negative { + return; + } // Get predicates implied by the trait, or only super predicates if we only care about self predicates. let predicates = if self.only_self { tcx.super_predicates_of(data.def_id()) 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>) { |
