Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use rustc_middle::ty::{
TypeVisitable, TypeVisitableExt, Unnormalized, fold_regions,
};
use rustc_session::lint::builtin::UNINHABITED_STATIC;
use rustc_span::sym;
use rustc_span::{DesugaringKind, sym};
use rustc_target::spec::{AbiMap, AbiMapping};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::traits;
Expand Down Expand Up @@ -2117,7 +2117,9 @@ fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalD
// * check for emptiness to detect lone user-written `?Sized` bounds
// * compare the param span to the pred span to detect lone user-written `Sized` bounds
let has_explicit_bounds = bounded_params.is_empty()
|| (*bounded_params).get(&param.index).is_some_and(|&&pred_sp| pred_sp != span);
|| (*bounded_params).get(&param.index).is_some_and(|&&pred_sp| {
!pred_sp.is_desugaring(DesugaringKind::DefaultBound { def: param.def_id })
});
let const_param_help = !has_explicit_bounds;

let mut diag = tcx.dcx().create_err(diagnostics::UnusedGenericParameter {
Expand Down
12 changes: 8 additions & 4 deletions compiler/rustc_hir_analysis/src/collect/item_bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,16 @@ fn associated_type_bounds<'tcx>(
&mut bounds,
item_ty,
hir_bounds,
ImpliedBoundsContext::AssociatedTypeOrImplTrait,
&[],
ImpliedBoundsContext::AssociatedType(assoc_item_def_id),
span,
);
icx.lowerer().add_default_traits(
&mut bounds,
item_ty,
hir_bounds,
ImpliedBoundsContext::AssociatedTypeOrImplTrait,
&[],
ImpliedBoundsContext::AssociatedType(assoc_item_def_id),
span,
);

Expand Down Expand Up @@ -384,14 +386,16 @@ fn opaque_type_bounds<'tcx>(
&mut bounds,
item_ty,
hir_bounds,
ImpliedBoundsContext::AssociatedTypeOrImplTrait,
&[],
ImpliedBoundsContext::ImplTrait,
span,
);
icx.lowerer().add_default_traits(
&mut bounds,
item_ty,
hir_bounds,
ImpliedBoundsContext::AssociatedTypeOrImplTrait,
&[],
ImpliedBoundsContext::ImplTrait,
span,
);
}
Expand Down
16 changes: 12 additions & 4 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,13 +200,15 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
&mut bounds,
tcx.types.self_param,
self_bounds,
&[],
ImpliedBoundsContext::TraitDef(def_id),
span,
);
icx.lowerer().add_default_traits(
&mut bounds,
tcx.types.self_param,
self_bounds,
&[],
ImpliedBoundsContext::TraitDef(def_id),
span,
);
Expand Down Expand Up @@ -239,14 +241,16 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
&mut bounds,
param_ty,
&[],
ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates),
hir_generics.predicates,
ImpliedBoundsContext::TyParam(param.def_id),
param.span,
);
icx.lowerer().add_default_traits(
&mut bounds,
param_ty,
&[],
ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates),
hir_generics.predicates,
ImpliedBoundsContext::TyParam(param.def_id),
param.span,
);
trace!(?bounds);
Expand Down Expand Up @@ -692,13 +696,15 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
&mut bounds,
self_param_ty,
superbounds,
&[],
ImpliedBoundsContext::TraitDef(trait_def_id),
item.span,
);
icx.lowerer().add_default_traits(
&mut bounds,
self_param_ty,
superbounds,
&[],
ImpliedBoundsContext::TraitDef(trait_def_id),
item.span,
);
Expand Down Expand Up @@ -994,14 +1000,16 @@ impl<'tcx> ItemCtxt<'tcx> {
&mut bounds,
param_ty,
&[],
ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates),
hir_generics.predicates,
ImpliedBoundsContext::TyParam(param.def_id),
param.span,
);
self.lowerer().add_default_traits(
&mut bounds,
param_ty,
&[],
ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates),
hir_generics.predicates,
ImpliedBoundsContext::TyParam(param.def_id),
param.span,
);
}
Expand Down
97 changes: 66 additions & 31 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use rustc_middle::ty::{
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
TypeVisitor, Upcast,
};
use rustc_span::{ErrorGuaranteed, Ident, Span, kw};
use rustc_span::{DesugaringKind, ErrorGuaranteed, Ident, Span, kw};
use rustc_trait_selection::traits;
use tracing::{debug, instrument};

Expand All @@ -25,17 +25,17 @@ use crate::hir_ty_lowering::{
#[derive(Debug, Default)]
struct CollectedBound {
/// `Trait`
positive: bool,
positive: Option<Span>,
/// `?Trait`
maybe: bool,
maybe: Option<Span>,
/// `!Trait`
negative: bool,
negative: Option<Span>,
}

impl CollectedBound {
/// Returns `true` if any of `Trait`, `?Trait` or `!Trait` were encountered.
fn any(&self) -> bool {
self.positive || self.maybe || self.negative
self.positive.is_some() || self.maybe.is_some() || self.negative.is_some()
}
}

Expand All @@ -59,7 +59,8 @@ impl CollectedSizednessBounds {

fn search_bounds_for<'tcx>(
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
context: ImpliedBoundsContext<'tcx>,
where_bounds: &'tcx [hir::WherePredicate<'tcx>],
context: ImpliedBoundsContext,
mut f: impl FnMut(&'tcx PolyTraitRef<'tcx>),
) {
let mut search_bounds = |hir_bounds: &'tcx [hir::GenericBound<'tcx>]| {
Expand All @@ -73,8 +74,8 @@ fn search_bounds_for<'tcx>(
};

search_bounds(hir_bounds);
if let ImpliedBoundsContext::TyParam(self_ty, where_clause) = context {
for clause in where_clause {
if let ImpliedBoundsContext::TyParam(self_ty) = context {
for clause in where_bounds {
if let hir::WherePredicateKind::BoundPredicate(pred) = clause.kind
&& pred.is_param_bound(self_ty.to_def_id())
{
Expand All @@ -86,19 +87,20 @@ fn search_bounds_for<'tcx>(

fn collect_bounds<'a, 'tcx>(
hir_bounds: &'a [hir::GenericBound<'tcx>],
context: ImpliedBoundsContext<'tcx>,
where_bounds: &'tcx [hir::WherePredicate<'tcx>],
context: ImpliedBoundsContext,
target_did: DefId,
) -> CollectedBound {
let mut collect_into = CollectedBound::default();
search_bounds_for(hir_bounds, context, |ptr| {
search_bounds_for(hir_bounds, where_bounds, context, |ptr| {
if !matches!(ptr.trait_ref.path.res, Res::Def(DefKind::Trait, did) if did == target_did) {
return;
}

match ptr.modifiers.polarity {
hir::BoundPolarity::Maybe(_) => collect_into.maybe = true,
hir::BoundPolarity::Negative(_) => collect_into.negative = true,
hir::BoundPolarity::Positive => collect_into.positive = true,
hir::BoundPolarity::Maybe(_) => collect_into.maybe = Some(ptr.span),
hir::BoundPolarity::Negative(_) => collect_into.negative = Some(ptr.span),
hir::BoundPolarity::Positive => collect_into.positive = Some(ptr.span),
}
});
collect_into
Expand All @@ -107,17 +109,18 @@ fn collect_bounds<'a, 'tcx>(
fn collect_sizedness_bounds<'tcx>(
tcx: TyCtxt<'tcx>,
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
context: ImpliedBoundsContext<'tcx>,
where_bounds: &'tcx [hir::WherePredicate<'tcx>],
context: ImpliedBoundsContext,
span: Span,
) -> CollectedSizednessBounds {
let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
let sized = collect_bounds(hir_bounds, context, sized_did);
let sized = collect_bounds(hir_bounds, where_bounds, context, sized_did);

let meta_sized_did = tcx.require_lang_item(hir::LangItem::MetaSized, span);
let meta_sized = collect_bounds(hir_bounds, context, meta_sized_did);
let meta_sized = collect_bounds(hir_bounds, where_bounds, context, meta_sized_did);

let pointee_sized_did = tcx.require_lang_item(hir::LangItem::PointeeSized, span);
let pointee_sized = collect_bounds(hir_bounds, context, pointee_sized_did);
let pointee_sized = collect_bounds(hir_bounds, where_bounds, context, pointee_sized_did);

CollectedSizednessBounds { sized, meta_sized, pointee_sized }
}
Expand Down Expand Up @@ -150,7 +153,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
self_ty: Ty<'tcx>,
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
context: ImpliedBoundsContext<'tcx>,
where_bounds: &'tcx [hir::WherePredicate<'tcx>],
context: ImpliedBoundsContext,
span: Span,
) {
let tcx = self.tcx();
Expand All @@ -177,28 +181,48 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
return;
}
}
ImpliedBoundsContext::TyParam(..) | ImpliedBoundsContext::AssociatedTypeOrImplTrait => {
}
ImpliedBoundsContext::TyParam(..)
| ImpliedBoundsContext::AssociatedType(..)
| ImpliedBoundsContext::TraitObject
| ImpliedBoundsContext::TraitAscription
| ImpliedBoundsContext::ImplTrait => {}
}

let collected = collect_sizedness_bounds(tcx, hir_bounds, context, span);
if (collected.sized.maybe || collected.sized.negative)
&& !collected.sized.positive
let collected = collect_sizedness_bounds(tcx, hir_bounds, where_bounds, context, span);
if let Some(span) = collected.sized.maybe.or(collected.sized.negative)
&& collected.sized.positive.is_none()
&& !collected.meta_sized.any()
&& !collected.pointee_sized.any()
{
// `?Sized` is equivalent to `MetaSized` (but only add the bound if there aren't any
// other explicit ones) - this can happen for trait aliases as well as bounds.
add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
} else if !collected.any() {
let span = match context {
ImpliedBoundsContext::TraitDef(def)
| ImpliedBoundsContext::TyParam(def)
| ImpliedBoundsContext::AssociatedType(def) => {
self.tcx().with_stable_hashing_context(|hcx| {
span.mark_with_reason(
None,
DesugaringKind::DefaultBound { def: def.into() },
span.edition(),
hcx,
)
})
}
_ => span,
};
match context {
ImpliedBoundsContext::TraitDef(..) => {
// If there are no explicit sizedness bounds on a trait then add a default
// `MetaSized` supertrait.
add_trait_bound(tcx, bounds, self_ty, meta_sized_did, span);
}
ImpliedBoundsContext::TyParam(..)
| ImpliedBoundsContext::AssociatedTypeOrImplTrait => {
| ImpliedBoundsContext::AssociatedType(..)
| ImpliedBoundsContext::TraitObject
| ImpliedBoundsContext::TraitAscription
| ImpliedBoundsContext::ImplTrait => {
// If there are no explicit sizedness bounds on a parameter then add a default
// `Sized` bound.
let sized_did = tcx.require_lang_item(hir::LangItem::Sized, span);
Expand All @@ -213,11 +237,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
self_ty: Ty<'tcx>,
hir_bounds: &[hir::GenericBound<'tcx>],
context: ImpliedBoundsContext<'tcx>,
where_bounds: &'tcx [hir::WherePredicate<'tcx>],
context: ImpliedBoundsContext,
span: Span,
) {
self.tcx().default_traits().iter().for_each(|default_trait| {
self.add_default_trait(*default_trait, bounds, self_ty, hir_bounds, context, span);
self.add_default_trait(
*default_trait,
bounds,
self_ty,
hir_bounds,
where_bounds,
context,
span,
);
});
}

Expand All @@ -230,7 +263,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
self_ty: Ty<'tcx>,
hir_bounds: &[hir::GenericBound<'tcx>],
context: ImpliedBoundsContext<'tcx>,
where_bounds: &'tcx [hir::WherePredicate<'tcx>],
context: ImpliedBoundsContext,
span: Span,
) {
let tcx = self.tcx();
Expand All @@ -244,7 +278,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}

if let Some(trait_did) = tcx.lang_items().get(trait_)
&& self.should_add_default_traits(trait_did, hir_bounds, context)
&& self.should_add_default_traits(trait_did, hir_bounds, where_bounds, context)
{
add_trait_bound(tcx, bounds, self_ty, trait_did, span);
}
Expand All @@ -255,9 +289,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
&self,
trait_def_id: DefId,
hir_bounds: &'a [hir::GenericBound<'tcx>],
context: ImpliedBoundsContext<'tcx>,
where_bounds: &'tcx [hir::WherePredicate<'tcx>],
context: ImpliedBoundsContext,
) -> bool {
let collected = collect_bounds(hir_bounds, context, trait_def_id);
let collected = collect_bounds(hir_bounds, where_bounds, context, trait_def_id);
!find_attr!(self.tcx(), crate, RustcNoImplicitBounds) && !collected.any()
}

Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
.iter()
.map(|&trait_ref| hir::GenericBound::Trait(trait_ref))
.collect::<Vec<_>>(),
ImpliedBoundsContext::AssociatedTypeOrImplTrait,
&[],
ImpliedBoundsContext::TraitObject,
span,
);

Expand Down
14 changes: 9 additions & 5 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,17 @@ use crate::{NoVariantNamed, check_c_variadic_abi};
/// The context in which an implied bound is being added to a item being lowered (i.e. a sizedness
/// trait or a default trait)
#[derive(Clone, Copy)]
pub(crate) enum ImpliedBoundsContext<'tcx> {
pub(crate) enum ImpliedBoundsContext {
/// An implied bound is added to a trait definition (i.e. a new supertrait), used when adding
/// a default `MetaSized` supertrait
TraitDef(LocalDefId),
/// An implied bound is added to a type parameter
TyParam(LocalDefId, &'tcx [hir::WherePredicate<'tcx>]),
/// An implied bound being added in any other context
AssociatedTypeOrImplTrait,
TyParam(LocalDefId),
/// Associated type bounds
AssociatedType(LocalDefId),
ImplTrait,
TraitObject,
TraitAscription,
}

/// A path segment that is semantically allowed to have generic arguments.
Expand Down Expand Up @@ -3093,7 +3096,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
&mut bounds,
self_ty,
hir_bounds,
ImpliedBoundsContext::AssociatedTypeOrImplTrait,
&[],
ImpliedBoundsContext::TraitAscription,
hir_ty.span,
);
self.register_trait_ascription_bounds(bounds, hir_ty.hir_id, hir_ty.span);
Expand Down
Loading
Loading