Rollup merge of #142693 - fmease:unbound-bettering, r=compiler-errors
More robustly deal with relaxed bounds and improve their diagnostics Scaffolding for https://github.com/rust-lang/rust/issues/135229 (CC https://github.com/rust-lang/rust/pull/135331) Fixes https://github.com/rust-lang/rust/issues/136944 (6th commit). Fixes https://github.com/rust-lang/rust/issues/142718 (8th commit).
This commit is contained in:
@@ -267,20 +267,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
||||
match predicate.kind {
|
||||
hir::WherePredicateKind::BoundPredicate(bound_pred) => {
|
||||
let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
|
||||
|
||||
let bound_vars = tcx.late_bound_vars(predicate.hir_id);
|
||||
// Keep the type around in a dummy predicate, in case of no bounds.
|
||||
// That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
|
||||
// is still checked for WF.
|
||||
|
||||
// This is a `where Ty:` (sic!).
|
||||
if bound_pred.bounds.is_empty() {
|
||||
if let ty::Param(_) = ty.kind() {
|
||||
// This is a `where T:`, which can be in the HIR from the
|
||||
// transformation that moves `?Sized` to `T`'s declaration.
|
||||
// We can skip the predicate because type parameters are
|
||||
// trivially WF, but also we *should*, to avoid exposing
|
||||
// users who never wrote `where Type:,` themselves, to
|
||||
// compiler/tooling bugs from not handling WF predicates.
|
||||
// We can skip the predicate because type parameters are trivially WF.
|
||||
} else {
|
||||
// Keep the type around in a dummy predicate. That way, it's not a complete
|
||||
// noop (see #53696) and `Ty` is still checked for WF.
|
||||
|
||||
let span = bound_pred.bounded_ty.span;
|
||||
let predicate = ty::Binder::bind_with_vars(
|
||||
ty::ClauseKind::WellFormed(ty.into()),
|
||||
|
||||
@@ -279,13 +279,6 @@ pub(crate) struct CopyImplOnTypeWithDtor {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_multiple_relaxed_default_bounds, code = E0203)]
|
||||
pub(crate) struct MultipleRelaxedDefaultBounds {
|
||||
#[primary_span]
|
||||
pub spans: Vec<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_copy_impl_on_non_adt, code = E0206)]
|
||||
pub(crate) struct CopyImplOnNonAdt {
|
||||
@@ -319,13 +312,6 @@ pub(crate) struct TraitObjectDeclaredWithNoTraits {
|
||||
pub trait_alias_span: Option<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_pointee_sized_trait_object)]
|
||||
pub(crate) struct PointeeSizedTraitObject {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_ambiguous_lifetime_bound, code = E0227)]
|
||||
pub(crate) struct AmbiguousLifetimeBound {
|
||||
|
||||
@@ -6,7 +6,7 @@ use rustc_errors::struct_span_code_err;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
|
||||
use rustc_hir::{AmbigArg, LangItem, PolyTraitRef};
|
||||
use rustc_hir::{AmbigArg, PolyTraitRef};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{
|
||||
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
||||
@@ -85,17 +85,17 @@ fn search_bounds_for<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_unbounds<'tcx>(
|
||||
fn collect_relaxed_bounds<'tcx>(
|
||||
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
||||
) -> SmallVec<[&'tcx PolyTraitRef<'tcx>; 1]> {
|
||||
let mut unbounds: SmallVec<[_; 1]> = SmallVec::new();
|
||||
let mut relaxed_bounds: SmallVec<[_; 1]> = SmallVec::new();
|
||||
search_bounds_for(hir_bounds, self_ty_where_predicates, |ptr| {
|
||||
if matches!(ptr.modifiers.polarity, hir::BoundPolarity::Maybe(_)) {
|
||||
unbounds.push(ptr);
|
||||
relaxed_bounds.push(ptr);
|
||||
}
|
||||
});
|
||||
unbounds
|
||||
relaxed_bounds
|
||||
}
|
||||
|
||||
fn collect_bounds<'a, 'tcx>(
|
||||
@@ -124,13 +124,13 @@ fn collect_sizedness_bounds<'tcx>(
|
||||
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
||||
span: Span,
|
||||
) -> CollectedSizednessBounds {
|
||||
let sized_did = tcx.require_lang_item(LangItem::Sized, span);
|
||||
let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
|
||||
let sized = collect_bounds(hir_bounds, self_ty_where_predicates, sized_did);
|
||||
|
||||
let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
|
||||
let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
|
||||
let meta_sized = collect_bounds(hir_bounds, self_ty_where_predicates, meta_sized_did);
|
||||
|
||||
let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
|
||||
let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
|
||||
let pointee_sized = collect_bounds(hir_bounds, self_ty_where_predicates, pointee_sized_did);
|
||||
|
||||
CollectedSizednessBounds { sized, meta_sized, pointee_sized }
|
||||
@@ -151,24 +151,6 @@ fn add_trait_bound<'tcx>(
|
||||
}
|
||||
|
||||
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
/// Skip `PointeeSized` bounds.
|
||||
///
|
||||
/// `PointeeSized` is a "fake bound" insofar as anywhere a `PointeeSized` bound exists, there
|
||||
/// is actually the absence of any bounds. This avoids limitations around non-global where
|
||||
/// clauses being preferred over item bounds (where `PointeeSized` bounds would be
|
||||
/// proven) - which can result in errors when a `PointeeSized` supertrait/bound/predicate is
|
||||
/// added to some items.
|
||||
pub(crate) fn should_skip_sizedness_bound<'hir>(
|
||||
&self,
|
||||
bound: &'hir hir::GenericBound<'tcx>,
|
||||
) -> bool {
|
||||
bound
|
||||
.trait_ref()
|
||||
.and_then(|tr| tr.trait_def_id())
|
||||
.map(|did| self.tcx().is_lang_item(did, LangItem::PointeeSized))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Adds sizedness bounds to a trait, trait alias, parameter, opaque type or associated type.
|
||||
///
|
||||
/// - On parameters, opaque type and associated types, add default `Sized` bound if no explicit
|
||||
@@ -193,8 +175,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
return;
|
||||
}
|
||||
|
||||
let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span);
|
||||
let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
|
||||
let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
|
||||
let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
|
||||
|
||||
// If adding sizedness bounds to a trait, then there are some relevant early exits
|
||||
if let Some(trait_did) = trait_did {
|
||||
@@ -209,9 +191,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Report invalid unbounds on sizedness-bounded generic parameters.
|
||||
let unbounds = collect_unbounds(hir_bounds, self_ty_where_predicates);
|
||||
self.check_and_report_invalid_unbounds_on_param(unbounds);
|
||||
// Report invalid relaxed bounds.
|
||||
// FIXME: Since we only call this validation function here in this function, we only
|
||||
// fully validate relaxed bounds in contexts where we perform
|
||||
// "sized elaboration". In most cases that doesn't matter because we *usually*
|
||||
// reject such relaxed bounds outright during AST lowering.
|
||||
// However, this can easily get out of sync! Ideally, we would perform this step
|
||||
// where we are guaranteed to catch *all* bounds like in
|
||||
// `Self::lower_poly_trait_ref`. List of concrete issues:
|
||||
// FIXME(more_maybe_bounds): We don't call this for e.g., trait object tys or
|
||||
// supertrait bounds!
|
||||
// FIXME(trait_alias, #143122): We don't call it for the RHS. Arguably however,
|
||||
// AST lowering should reject them outright.
|
||||
// FIXME(associated_type_bounds): We don't call this for them. However, AST
|
||||
// lowering should reject them outright (#135229).
|
||||
let bounds = collect_relaxed_bounds(hir_bounds, self_ty_where_predicates);
|
||||
self.check_and_report_invalid_relaxed_bounds(bounds);
|
||||
}
|
||||
|
||||
let collected = collect_sizedness_bounds(tcx, hir_bounds, self_ty_where_predicates, span);
|
||||
@@ -231,7 +226,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
} else {
|
||||
// If there are no explicit sizedness bounds on a parameter then add a default
|
||||
// `Sized` bound.
|
||||
let sized_did = tcx.require_lang_item(LangItem::Sized, span);
|
||||
let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
|
||||
add_trait_bound(tcx, bounds, self_ty, sized_did, span);
|
||||
}
|
||||
}
|
||||
@@ -463,10 +458,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
'tcx: 'hir,
|
||||
{
|
||||
for hir_bound in hir_bounds {
|
||||
if self.should_skip_sizedness_bound(hir_bound) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// In order to avoid cycles, when we're lowering `SelfTraitThatDefines`,
|
||||
// we skip over any traits that don't define the given associated type.
|
||||
if let PredicateFilter::SelfTraitThatDefines(assoc_ident) = predicate_filter {
|
||||
@@ -482,12 +473,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
|
||||
match hir_bound {
|
||||
hir::GenericBound::Trait(poly_trait_ref) => {
|
||||
let hir::TraitBoundModifiers { constness, polarity } = poly_trait_ref.modifiers;
|
||||
let _ = self.lower_poly_trait_ref(
|
||||
&poly_trait_ref.trait_ref,
|
||||
poly_trait_ref.span,
|
||||
constness,
|
||||
polarity,
|
||||
poly_trait_ref,
|
||||
param_ty,
|
||||
bounds,
|
||||
predicate_filter,
|
||||
|
||||
@@ -2,7 +2,6 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::struct_span_code_err;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS;
|
||||
use rustc_middle::ty::elaborate::ClauseWithSupertraitSpan;
|
||||
@@ -18,9 +17,7 @@ use tracing::{debug, instrument};
|
||||
|
||||
use super::HirTyLowerer;
|
||||
use crate::errors::SelfInTypeAlias;
|
||||
use crate::hir_ty_lowering::{
|
||||
GenericArgCountMismatch, GenericArgCountResult, PredicateFilter, RegionInferReason,
|
||||
};
|
||||
use crate::hir_ty_lowering::{GenericArgCountMismatch, PredicateFilter, RegionInferReason};
|
||||
|
||||
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
/// Lower a trait object type from the HIR to our internal notion of a type.
|
||||
@@ -38,24 +35,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
|
||||
let mut user_written_bounds = Vec::new();
|
||||
let mut potential_assoc_types = Vec::new();
|
||||
for trait_bound in hir_bounds.iter() {
|
||||
if let hir::BoundPolarity::Maybe(_) = trait_bound.modifiers.polarity {
|
||||
continue;
|
||||
}
|
||||
if let GenericArgCountResult {
|
||||
correct:
|
||||
Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
|
||||
..
|
||||
} = self.lower_poly_trait_ref(
|
||||
&trait_bound.trait_ref,
|
||||
trait_bound.span,
|
||||
trait_bound.modifiers.constness,
|
||||
hir::BoundPolarity::Positive,
|
||||
for poly_trait_ref in hir_bounds.iter() {
|
||||
let result = self.lower_poly_trait_ref(
|
||||
poly_trait_ref,
|
||||
dummy_self,
|
||||
&mut user_written_bounds,
|
||||
PredicateFilter::SelfOnly,
|
||||
) {
|
||||
potential_assoc_types.extend(cur_potential_assoc_types);
|
||||
);
|
||||
if let Err(GenericArgCountMismatch { invalid_args, .. }) = result.correct {
|
||||
potential_assoc_types.extend(invalid_args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,13 +69,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
let guar = self.report_trait_object_addition_traits(®ular_traits);
|
||||
return Ty::new_error(tcx, guar);
|
||||
}
|
||||
// We don't support `PointeeSized` principals
|
||||
let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span);
|
||||
if regular_traits.iter().any(|(pred, _)| pred.def_id() == pointee_sized_did) {
|
||||
let guar = self.report_pointee_sized_trait_object(span);
|
||||
return Ty::new_error(tcx, guar);
|
||||
}
|
||||
|
||||
// Don't create a dyn trait if we have errors in the principal.
|
||||
if let Err(guar) = regular_traits.error_reported() {
|
||||
return Ty::new_error(tcx, guar);
|
||||
|
||||
@@ -8,7 +8,7 @@ use rustc_errors::{
|
||||
};
|
||||
use rustc_hir::def::{CtorOf, DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::{self as hir, HirId, LangItem, PolyTraitRef};
|
||||
use rustc_hir::{self as hir, HirId, PolyTraitRef};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::fast_reject::{TreatParams, simplify_type};
|
||||
use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
|
||||
@@ -29,59 +29,54 @@ use tracing::debug;
|
||||
use super::InherentAssocCandidate;
|
||||
use crate::errors::{
|
||||
self, AssocItemConstraintsNotAllowedHere, ManualImplementation, MissingTypeParams,
|
||||
ParenthesizedFnTraitExpansion, PointeeSizedTraitObject, TraitObjectDeclaredWithNoTraits,
|
||||
ParenthesizedFnTraitExpansion, TraitObjectDeclaredWithNoTraits,
|
||||
};
|
||||
use crate::fluent_generated as fluent;
|
||||
use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer};
|
||||
|
||||
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
/// Check for multiple relaxed default bounds and relaxed bounds of non-sizedness traits.
|
||||
pub(crate) fn check_and_report_invalid_unbounds_on_param(
|
||||
/// Check for duplicate relaxed bounds and relaxed bounds of non-default traits.
|
||||
pub(crate) fn check_and_report_invalid_relaxed_bounds(
|
||||
&self,
|
||||
unbounds: SmallVec<[&PolyTraitRef<'_>; 1]>,
|
||||
relaxed_bounds: SmallVec<[&PolyTraitRef<'_>; 1]>,
|
||||
) {
|
||||
let tcx = self.tcx();
|
||||
|
||||
let sized_did = tcx.require_lang_item(LangItem::Sized, DUMMY_SP);
|
||||
let mut grouped_bounds = FxIndexMap::<_, Vec<_>>::default();
|
||||
|
||||
let mut unique_bounds = FxIndexSet::default();
|
||||
let mut seen_repeat = false;
|
||||
for unbound in &unbounds {
|
||||
if let Res::Def(DefKind::Trait, unbound_def_id) = unbound.trait_ref.path.res {
|
||||
seen_repeat |= !unique_bounds.insert(unbound_def_id);
|
||||
for bound in &relaxed_bounds {
|
||||
if let Res::Def(DefKind::Trait, trait_def_id) = bound.trait_ref.path.res {
|
||||
grouped_bounds.entry(trait_def_id).or_default().push(bound.span);
|
||||
}
|
||||
}
|
||||
|
||||
if unbounds.len() > 1 {
|
||||
let err = errors::MultipleRelaxedDefaultBounds {
|
||||
spans: unbounds.iter().map(|ptr| ptr.span).collect(),
|
||||
};
|
||||
|
||||
if seen_repeat {
|
||||
tcx.dcx().emit_err(err);
|
||||
} else if !tcx.features().more_maybe_bounds() {
|
||||
tcx.sess.create_feature_err(err, sym::more_maybe_bounds).emit();
|
||||
};
|
||||
for (trait_def_id, spans) in grouped_bounds {
|
||||
if spans.len() > 1 {
|
||||
let name = tcx.item_name(trait_def_id);
|
||||
self.dcx()
|
||||
.struct_span_err(spans, format!("duplicate relaxed `{name}` bounds"))
|
||||
.with_code(E0203)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
||||
for unbound in unbounds {
|
||||
if let Res::Def(DefKind::Trait, did) = unbound.trait_ref.path.res
|
||||
&& ((did == sized_did) || tcx.is_default_trait(did))
|
||||
let sized_def_id = tcx.require_lang_item(hir::LangItem::Sized, DUMMY_SP);
|
||||
|
||||
for bound in relaxed_bounds {
|
||||
if let Res::Def(DefKind::Trait, def_id) = bound.trait_ref.path.res
|
||||
&& (def_id == sized_def_id || tcx.is_default_trait(def_id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let unbound_traits = match tcx.sess.opts.unstable_opts.experimental_default_bounds {
|
||||
true => "`?Sized` and `experimental_default_bounds`",
|
||||
false => "`?Sized`",
|
||||
};
|
||||
self.dcx().span_err(
|
||||
unbound.span,
|
||||
format!(
|
||||
"relaxing a default bound only does something for {}; all other traits are \
|
||||
not bound by default",
|
||||
unbound_traits
|
||||
),
|
||||
bound.span,
|
||||
if tcx.sess.opts.unstable_opts.experimental_default_bounds
|
||||
|| tcx.features().more_maybe_bounds()
|
||||
{
|
||||
"bound modifier `?` can only be applied to default traits like `Sized`"
|
||||
} else {
|
||||
"bound modifier `?` can only be applied to `Sized`"
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1410,10 +1405,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
|
||||
self.dcx().emit_err(TraitObjectDeclaredWithNoTraits { span, trait_alias_span })
|
||||
}
|
||||
|
||||
pub(super) fn report_pointee_sized_trait_object(&self, span: Span) -> ErrorGuaranteed {
|
||||
self.dcx().emit_err(PointeeSizedTraitObject { span })
|
||||
}
|
||||
}
|
||||
|
||||
/// Emit an error for the given associated item constraint.
|
||||
|
||||
@@ -747,18 +747,46 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
/// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>`
|
||||
/// where `'a` is a bound region at depth 0. Similarly, the `trait_ref` would be `Bar<'a>`.
|
||||
/// The lowered poly-trait-ref will track this binder explicitly, however.
|
||||
#[instrument(level = "debug", skip(self, span, constness, bounds))]
|
||||
#[instrument(level = "debug", skip(self, bounds))]
|
||||
pub(crate) fn lower_poly_trait_ref(
|
||||
&self,
|
||||
trait_ref: &hir::TraitRef<'tcx>,
|
||||
span: Span,
|
||||
constness: hir::BoundConstness,
|
||||
polarity: hir::BoundPolarity,
|
||||
poly_trait_ref: &hir::PolyTraitRef<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
||||
predicate_filter: PredicateFilter,
|
||||
) -> GenericArgCountResult {
|
||||
let tcx = self.tcx();
|
||||
|
||||
// We use the *resolved* bound vars later instead of the HIR ones since the former
|
||||
// also include the bound vars of the overarching predicate if applicable.
|
||||
let hir::PolyTraitRef { bound_generic_params: _, modifiers, ref trait_ref, span } =
|
||||
*poly_trait_ref;
|
||||
let hir::TraitBoundModifiers { constness, polarity } = modifiers;
|
||||
|
||||
let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
|
||||
|
||||
// Relaxed bounds `?Trait` and `PointeeSized` bounds aren't represented in the `middle::ty` IR
|
||||
// as they denote the *absence* of a default bound. However, we can't bail out early here since
|
||||
// we still need to perform several validation steps (see below). Instead, simply "pour" all
|
||||
// resulting bounds "down the drain", i.e., into a new `Vec` that just gets dropped at the end.
|
||||
let (polarity, bounds) = match polarity {
|
||||
rustc_ast::BoundPolarity::Positive
|
||||
if tcx.is_lang_item(trait_def_id, hir::LangItem::PointeeSized) =>
|
||||
{
|
||||
// To elaborate on the comment directly above, regarding `PointeeSized` specifically,
|
||||
// we don't "reify" such bounds to avoid trait system limitations -- namely,
|
||||
// non-global where-clauses being preferred over item bounds (where `PointeeSized`
|
||||
// bounds would be proven) -- which can result in errors when a `PointeeSized`
|
||||
// supertrait / bound / predicate is added to some items.
|
||||
(ty::PredicatePolarity::Positive, &mut Vec::new())
|
||||
}
|
||||
rustc_ast::BoundPolarity::Positive => (ty::PredicatePolarity::Positive, bounds),
|
||||
rustc_ast::BoundPolarity::Negative(_) => (ty::PredicatePolarity::Negative, bounds),
|
||||
rustc_ast::BoundPolarity::Maybe(_) => {
|
||||
(ty::PredicatePolarity::Positive, &mut Vec::new())
|
||||
}
|
||||
};
|
||||
|
||||
let trait_segment = trait_ref.path.segments.last().unwrap();
|
||||
|
||||
let _ = self.prohibit_generic_args(
|
||||
@@ -775,7 +803,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
Some(self_ty),
|
||||
);
|
||||
|
||||
let tcx = self.tcx();
|
||||
let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id);
|
||||
debug!(?bound_vars);
|
||||
|
||||
@@ -786,27 +813,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
|
||||
debug!(?poly_trait_ref);
|
||||
|
||||
let polarity = match polarity {
|
||||
rustc_ast::BoundPolarity::Positive => ty::PredicatePolarity::Positive,
|
||||
rustc_ast::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative,
|
||||
rustc_ast::BoundPolarity::Maybe(_) => {
|
||||
// Validate associated type at least. We may want to reject these
|
||||
// outright in the future...
|
||||
for constraint in trait_segment.args().constraints {
|
||||
let _ = self.lower_assoc_item_constraint(
|
||||
trait_ref.hir_ref_id,
|
||||
poly_trait_ref,
|
||||
constraint,
|
||||
&mut Default::default(),
|
||||
&mut Default::default(),
|
||||
constraint.span,
|
||||
predicate_filter,
|
||||
);
|
||||
}
|
||||
return arg_count;
|
||||
}
|
||||
};
|
||||
|
||||
// We deal with const conditions later.
|
||||
match predicate_filter {
|
||||
PredicateFilter::All
|
||||
@@ -909,7 +915,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
||||
// Don't register any associated item constraints for negative bounds,
|
||||
// since we should have emitted an error for them earlier, and they
|
||||
// would not be well-formed!
|
||||
if polarity != ty::PredicatePolarity::Positive {
|
||||
if polarity == ty::PredicatePolarity::Negative {
|
||||
self.dcx().span_delayed_bug(
|
||||
constraint.span,
|
||||
"negative trait bounds should not have assoc item constraints",
|
||||
|
||||
Reference in New Issue
Block a user