diff options
| author | bors <bors@rust-lang.org> | 2023-05-02 06:36:44 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-05-02 06:36:44 +0000 |
| commit | 7b99493492ad59c7a44c65373558175db42b4151 (patch) | |
| tree | 3175b32e64b2e498d623f3830be4faabd89ad892 /compiler/rustc_hir_analysis/src | |
| parent | 5133e154590991203c84702ef59482f729b19bbf (diff) | |
| parent | 2e3373c231fdd7ce607acd2339bfee501322e8c6 (diff) | |
| download | rust-7b99493492ad59c7a44c65373558175db42b4151.tar.gz rust-7b99493492ad59c7a44c65373558175db42b4151.zip | |
Auto merge of #111089 - Dylan-DPC:rollup-b8oj6du, r=Dylan-DPC
Rollup of 7 pull requests Successful merges: - #105076 (Refactor core::char::EscapeDefault and co. structures) - #108161 (Add `ConstParamTy` trait) - #108668 (Stabilize debugger_visualizer) - #110512 (Fix elaboration with associated type bounds) - #110895 (Remove `all` in target_thread_local cfg) - #110955 (uplift `clippy::clone_double_ref` as `suspicious_double_ref_op`) - #111048 (Mark`feature(return_position_impl_trait_in_trait)` and`feature(async_fn_in_trait)` as not incomplete) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
| -rw-r--r-- | compiler/rustc_hir_analysis/src/astconv/mod.rs | 70 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/coherence/builtin.rs | 255 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/collect/item_bounds.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/collect/predicates_of.rs | 105 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/errors.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/lib.rs | 3 |
6 files changed, 267 insertions, 180 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 709dea43d84..6cb008bc5f8 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -56,6 +56,9 @@ use std::slice; #[derive(Debug)] pub struct PathSeg(pub DefId, pub usize); +#[derive(Copy, Clone, Debug)] +pub struct OnlySelfBounds(pub bool); + pub trait AstConv<'tcx> { fn tcx(&self) -> TyCtxt<'tcx>; @@ -670,6 +673,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { args: &GenericArgs<'_>, infer_args: bool, self_ty: Ty<'tcx>, + only_self_bounds: OnlySelfBounds, ) -> GenericArgCountResult { let (substs, arg_count) = self.create_substs_for_ast_path( trait_ref_span, @@ -706,6 +710,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &mut dup_bindings, binding_span.unwrap_or(binding.span), constness, + only_self_bounds, ); // Okay to ignore `Err` because of `ErrorGuaranteed` (see above). } @@ -741,6 +746,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Ty<'tcx>, bounds: &mut Bounds<'tcx>, speculative: bool, + only_self_bounds: OnlySelfBounds, ) -> GenericArgCountResult { let hir_id = trait_ref.hir_ref_id; let binding_span = None; @@ -766,6 +772,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { args, infer_args, self_ty, + only_self_bounds, ) } @@ -777,6 +784,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { args: &GenericArgs<'_>, self_ty: Ty<'tcx>, bounds: &mut Bounds<'tcx>, + only_self_bounds: OnlySelfBounds, ) { let binding_span = Some(span); let constness = ty::BoundConstness::NotConst; @@ -799,6 +807,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { args, infer_args, self_ty, + only_self_bounds, ); } @@ -947,6 +956,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ast_bounds: I, bounds: &mut Bounds<'tcx>, bound_vars: &'tcx ty::List<ty::BoundVariableKind>, + only_self_bounds: OnlySelfBounds, ) { for ast_bound in ast_bounds { match ast_bound { @@ -964,11 +974,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { param_ty, bounds, false, + only_self_bounds, ); } &hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => { self.instantiate_lang_item_trait_ref( - lang_item, span, hir_id, args, param_ty, bounds, + lang_item, + span, + hir_id, + args, + param_ty, + bounds, + only_self_bounds, ); } hir::GenericBound::Outlives(lifetime) => { @@ -1006,8 +1023,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { &self, param_ty: Ty<'tcx>, ast_bounds: &[hir::GenericBound<'_>], + only_self_bounds: OnlySelfBounds, ) -> Bounds<'tcx> { - self.compute_bounds_inner(param_ty, ast_bounds) + let mut bounds = Bounds::default(); + self.add_bounds( + param_ty, + ast_bounds.iter(), + &mut bounds, + ty::List::empty(), + only_self_bounds, + ); + debug!(?bounds); + + bounds } /// Convert the bounds in `ast_bounds` that refer to traits which define an associated type @@ -1029,17 +1057,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - self.compute_bounds_inner(param_ty, &result) - } - - fn compute_bounds_inner( - &self, - param_ty: Ty<'tcx>, - ast_bounds: &[hir::GenericBound<'_>], - ) -> Bounds<'tcx> { let mut bounds = Bounds::default(); - - self.add_bounds(param_ty, ast_bounds.iter(), &mut bounds, ty::List::empty()); + self.add_bounds( + param_ty, + result.iter(), + &mut bounds, + ty::List::empty(), + OnlySelfBounds(true), + ); debug!(?bounds); bounds @@ -1062,6 +1087,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { dup_bindings: &mut FxHashMap<DefId, Span>, path_span: Span, constness: ty::BoundConstness, + only_self_bounds: OnlySelfBounds, ) -> Result<(), ErrorGuaranteed> { // Given something like `U: SomeTrait<T = X>`, we want to produce a // predicate like `<U as SomeTrait>::T = X`. This is somewhat @@ -1361,8 +1387,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty` // parameter to have a skipped binder. - let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder()); - self.add_bounds(param_ty, ast_bounds.iter(), bounds, projection_ty.bound_vars()); + // + // NOTE: If `only_self_bounds` is true, do NOT expand this associated + // type bound into a trait predicate, since we only want to add predicates + // for the `Self` type. + if !only_self_bounds.0 { + let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder()); + self.add_bounds( + param_ty, + ast_bounds.iter(), + bounds, + projection_ty.bound_vars(), + only_self_bounds, + ); + } } } Ok(()) @@ -1403,6 +1441,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { dummy_self, &mut bounds, false, + // FIXME: This should be `true`, but we don't really handle + // associated type bounds or type aliases in objects in a way + // that makes this meaningful, I think. + OnlySelfBounds(false), ) { potential_assoc_types.extend(cur_potential_assoc_types); } diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 611ce13b739..0f450ae67b7 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -1,9 +1,11 @@ //! Check properties that are required by built-in traits and set //! up data structures required by type-checking/codegen. -use crate::errors::{CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem}; +use crate::errors::{ + ConstParamTyImplOnNonAdt, CopyImplOnNonAdt, CopyImplOnTypeWithDtor, DropImplOnWrongItem, +}; use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{struct_span_err, MultiSpan}; +use rustc_errors::{struct_span_err, ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; @@ -14,9 +16,11 @@ use rustc_infer::infer::{DefineOpaqueTypes, TyCtxtInferExt}; use rustc_infer::traits::Obligation; use rustc_middle::ty::adjustment::CoerceUnsizedInfo; use rustc_middle::ty::{self, suggest_constraining_type_params, Ty, TyCtxt, TypeVisitableExt}; +use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::misc::{ - type_allowed_to_implement_copy, CopyImplementationError, InfringingFieldsReason, + type_allowed_to_implement_const_param_ty, type_allowed_to_implement_copy, + ConstParamTyImplementationError, CopyImplementationError, InfringingFieldsReason, }; use rustc_trait_selection::traits::ObligationCtxt; use rustc_trait_selection::traits::{self, ObligationCause}; @@ -27,6 +31,7 @@ pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) { Checker { tcx, trait_def_id } .check(lang_items.drop_trait(), visit_implementation_of_drop) .check(lang_items.copy_trait(), visit_implementation_of_copy) + .check(lang_items.const_param_ty_trait(), visit_implementation_of_const_param_ty) .check(lang_items.coerce_unsized_trait(), visit_implementation_of_coerce_unsized) .check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn); } @@ -83,110 +88,7 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { match type_allowed_to_implement_copy(tcx, param_env, self_type, cause) { Ok(()) => {} Err(CopyImplementationError::InfringingFields(fields)) => { - let mut err = struct_span_err!( - tcx.sess, - span, - E0204, - "the trait `Copy` cannot be implemented for this type" - ); - - // We'll try to suggest constraining type parameters to fulfill the requirements of - // their `Copy` implementation. - let mut errors: BTreeMap<_, Vec<_>> = Default::default(); - let mut bounds = vec![]; - - let mut seen_tys = FxHashSet::default(); - - for (field, ty, reason) in fields { - // Only report an error once per type. - if !seen_tys.insert(ty) { - continue; - } - - let field_span = tcx.def_span(field.did); - err.span_label(field_span, "this field does not implement `Copy`"); - - match reason { - InfringingFieldsReason::Fulfill(fulfillment_errors) => { - for error in fulfillment_errors { - let error_predicate = error.obligation.predicate; - // Only note if it's not the root obligation, otherwise it's trivial and - // should be self-explanatory (i.e. a field literally doesn't implement Copy). - - // FIXME: This error could be more descriptive, especially if the error_predicate - // contains a foreign type or if it's a deeply nested type... - if error_predicate != error.root_obligation.predicate { - errors - .entry((ty.to_string(), error_predicate.to_string())) - .or_default() - .push(error.obligation.cause.span); - } - if let ty::PredicateKind::Clause(ty::Clause::Trait( - ty::TraitPredicate { - trait_ref, - polarity: ty::ImplPolarity::Positive, - .. - }, - )) = error_predicate.kind().skip_binder() - { - let ty = trait_ref.self_ty(); - if let ty::Param(_) = ty.kind() { - bounds.push(( - format!("{ty}"), - trait_ref.print_only_trait_path().to_string(), - Some(trait_ref.def_id), - )); - } - } - } - } - InfringingFieldsReason::Regions(region_errors) => { - for error in region_errors { - let ty = ty.to_string(); - match error { - RegionResolutionError::ConcreteFailure(origin, a, b) => { - let predicate = format!("{b}: {a}"); - errors - .entry((ty.clone(), predicate.clone())) - .or_default() - .push(origin.span()); - if let ty::RegionKind::ReEarlyBound(ebr) = *b && ebr.has_name() { - bounds.push((b.to_string(), a.to_string(), None)); - } - } - RegionResolutionError::GenericBoundFailure(origin, a, b) => { - let predicate = format!("{a}: {b}"); - errors - .entry((ty.clone(), predicate.clone())) - .or_default() - .push(origin.span()); - if let infer::region_constraints::GenericKind::Param(_) = a { - bounds.push((a.to_string(), b.to_string(), None)); - } - } - _ => continue, - } - } - } - } - } - for ((ty, error_predicate), spans) in errors { - let span: MultiSpan = spans.into(); - err.span_note( - span, - &format!("the `Copy` impl for `{}` requires that `{}`", ty, error_predicate), - ); - } - suggest_constraining_type_params( - tcx, - tcx.hir().get_generics(impl_did).expect("impls always have generics"), - &mut err, - bounds.iter().map(|(param, constraint, def_id)| { - (param.as_str(), constraint.as_str(), *def_id) - }), - None, - ); - err.emit(); + infringing_fields_error(tcx, fields, LangItem::Copy, impl_did, span); } Err(CopyImplementationError::NotAnAdt) => { tcx.sess.emit_err(CopyImplOnNonAdt { span }); @@ -197,6 +99,29 @@ fn visit_implementation_of_copy(tcx: TyCtxt<'_>, impl_did: LocalDefId) { } } +fn visit_implementation_of_const_param_ty(tcx: TyCtxt<'_>, impl_did: LocalDefId) { + let self_type = tcx.type_of(impl_did).subst_identity(); + assert!(!self_type.has_escaping_bound_vars()); + + let param_env = tcx.param_env(impl_did); + + let span = match tcx.hir().expect_item(impl_did).expect_impl() { + hir::Impl { polarity: hir::ImplPolarity::Negative(_), .. } => return, + impl_ => impl_.self_ty.span, + }; + + let cause = traits::ObligationCause::misc(span, impl_did); + match type_allowed_to_implement_const_param_ty(tcx, param_env, self_type, cause) { + Ok(()) => {} + Err(ConstParamTyImplementationError::InfrigingFields(fields)) => { + infringing_fields_error(tcx, fields, LangItem::ConstParamTy, impl_did, span); + } + Err(ConstParamTyImplementationError::NotAnAdtOrBuiltinAllowed) => { + tcx.sess.emit_err(ConstParamTyImplOnNonAdt { span }); + } + } +} + fn visit_implementation_of_coerce_unsized(tcx: TyCtxt<'_>, impl_did: LocalDefId) { debug!("visit_implementation_of_coerce_unsized: impl_did={:?}", impl_did); @@ -593,3 +518,119 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe CoerceUnsizedInfo { custom_kind: kind } } + +fn infringing_fields_error( + tcx: TyCtxt<'_>, + fields: Vec<(&ty::FieldDef, Ty<'_>, InfringingFieldsReason<'_>)>, + lang_item: LangItem, + impl_did: LocalDefId, + impl_span: Span, +) -> ErrorGuaranteed { + let trait_did = tcx.require_lang_item(lang_item, Some(impl_span)); + + let trait_name = tcx.def_path_str(trait_did); + + let mut err = struct_span_err!( + tcx.sess, + impl_span, + E0204, + "the trait `{trait_name}` cannot be implemented for this type" + ); + + // We'll try to suggest constraining type parameters to fulfill the requirements of + // their `Copy` implementation. + let mut errors: BTreeMap<_, Vec<_>> = Default::default(); + let mut bounds = vec![]; + + let mut seen_tys = FxHashSet::default(); + + for (field, ty, reason) in fields { + // Only report an error once per type. + if !seen_tys.insert(ty) { + continue; + } + + let field_span = tcx.def_span(field.did); + err.span_label(field_span, format!("this field does not implement `{trait_name}`")); + + match reason { + InfringingFieldsReason::Fulfill(fulfillment_errors) => { + for error in fulfillment_errors { + let error_predicate = error.obligation.predicate; + // Only note if it's not the root obligation, otherwise it's trivial and + // should be self-explanatory (i.e. a field literally doesn't implement Copy). + + // FIXME: This error could be more descriptive, especially if the error_predicate + // contains a foreign type or if it's a deeply nested type... + if error_predicate != error.root_obligation.predicate { + errors + .entry((ty.to_string(), error_predicate.to_string())) + .or_default() + .push(error.obligation.cause.span); + } + if let ty::PredicateKind::Clause(ty::Clause::Trait(ty::TraitPredicate { + trait_ref, + polarity: ty::ImplPolarity::Positive, + .. + })) = error_predicate.kind().skip_binder() + { + let ty = trait_ref.self_ty(); + if let ty::Param(_) = ty.kind() { + bounds.push(( + format!("{ty}"), + trait_ref.print_only_trait_path().to_string(), + Some(trait_ref.def_id), + )); + } + } + } + } + InfringingFieldsReason::Regions(region_errors) => { + for error in region_errors { + let ty = ty.to_string(); + match error { + RegionResolutionError::ConcreteFailure(origin, a, b) => { + let predicate = format!("{b}: {a}"); + errors + .entry((ty.clone(), predicate.clone())) + .or_default() + .push(origin.span()); + if let ty::RegionKind::ReEarlyBound(ebr) = *b && ebr.has_name() { + bounds.push((b.to_string(), a.to_string(), None)); + } + } + RegionResolutionError::GenericBoundFailure(origin, a, b) => { + let predicate = format!("{a}: {b}"); + errors + .entry((ty.clone(), predicate.clone())) + .or_default() + .push(origin.span()); + if let infer::region_constraints::GenericKind::Param(_) = a { + bounds.push((a.to_string(), b.to_string(), None)); + } + } + _ => continue, + } + } + } + } + } + for ((ty, error_predicate), spans) in errors { + let span: MultiSpan = spans.into(); + err.span_note( + span, + format!("the `{trait_name}` impl for `{ty}` requires that `{error_predicate}`"), + ); + } + suggest_constraining_type_params( + tcx, + tcx.hir().get_generics(impl_did).expect("impls always have generics"), + &mut err, + bounds + .iter() + .map(|(param, constraint, def_id)| (param.as_str(), constraint.as_str(), *def_id)), + None, + ); + + err.emit() +} diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 80d6bc7db9e..948b903e509 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -1,5 +1,5 @@ use super::ItemCtxt; -use crate::astconv::AstConv; +use crate::astconv::{AstConv, OnlySelfBounds}; use rustc_hir as hir; use rustc_infer::traits::util; use rustc_middle::ty::subst::InternalSubsts; @@ -26,7 +26,7 @@ fn associated_type_bounds<'tcx>( ); let icx = ItemCtxt::new(tcx, assoc_item_def_id); - let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds); + let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false)); // Associated types are implicitly sized unless a `?Sized` bound is found icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span); @@ -67,7 +67,7 @@ fn opaque_type_bounds<'tcx>( ) -> &'tcx [(ty::Predicate<'tcx>, Span)] { ty::print::with_no_queries!({ let icx = ItemCtxt::new(tcx, opaque_def_id); - let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds); + let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false)); // Opaque types are implicitly sized unless a `?Sized` bound is found icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span); debug!(?bounds); diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 8c414521b76..83470342a76 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -1,4 +1,4 @@ -use crate::astconv::AstConv; +use crate::astconv::{AstConv, OnlySelfBounds}; use crate::bounds::Bounds; use crate::collect::ItemCtxt; use crate::constrained_generic_params as cgp; @@ -14,9 +14,6 @@ use rustc_middle::ty::{GenericPredicates, ToPredicate}; use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, DUMMY_SP}; -#[derive(Debug)] -struct OnlySelfBounds(bool); - /// Returns a list of all type predicates (explicit and implicit) for the definition with /// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus /// `Self: Trait` predicates for traits. @@ -99,8 +96,9 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen | ItemKind::Struct(_, generics) | ItemKind::Union(_, generics) => generics, - ItemKind::Trait(_, _, generics, ..) | ItemKind::TraitAlias(generics, _) => { - is_trait = Some(ty::TraitRef::identity(tcx, def_id.to_def_id())); + ItemKind::Trait(_, _, generics, self_bounds, ..) + | ItemKind::TraitAlias(generics, self_bounds) => { + is_trait = Some(self_bounds); generics } ItemKind::OpaqueTy(OpaqueTy { generics, .. }) => generics, @@ -122,10 +120,14 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen // Below we'll consider the bounds on the type parameters (including `Self`) // and the explicit where-clauses, but to get the full set of predicates - // on a trait we need to add in the supertrait bounds and bounds found on - // associated types. - if let Some(_trait_ref) = is_trait { - predicates.extend(tcx.implied_predicates_of(def_id).predicates.iter().cloned()); + // on a trait we must also consider the bounds that follow the trait's name, + // like `trait Foo: A + B + C`. + if let Some(self_bounds) = is_trait { + predicates.extend( + icx.astconv() + .compute_bounds(tcx.types.self_param, self_bounds, OnlySelfBounds(false)) + .predicates(), + ); } // In default impls, we can assume that the self type implements @@ -225,7 +227,13 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen } let mut bounds = Bounds::default(); - icx.astconv().add_bounds(ty, bound_pred.bounds.iter(), &mut bounds, bound_vars); + icx.astconv().add_bounds( + ty, + bound_pred.bounds.iter(), + &mut bounds, + bound_vars, + OnlySelfBounds(false), + ); predicates.extend(bounds.predicates()); } @@ -608,7 +616,7 @@ pub(super) fn implied_predicates_with_filter( let (superbounds, where_bounds_that_match) = match filter { PredicateFilter::All => ( // Convert the bounds that follow the colon (or equal in trait aliases) - icx.astconv().compute_bounds(self_param_ty, bounds), + icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(false)), // Also include all where clause bounds icx.type_parameter_bounds_in_generics( generics, @@ -620,7 +628,7 @@ pub(super) fn implied_predicates_with_filter( ), PredicateFilter::SelfOnly => ( // Convert the bounds that follow the colon (or equal in trait aliases) - icx.astconv().compute_bounds(self_param_ty, bounds), + icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(true)), // Include where clause bounds for `Self` icx.type_parameter_bounds_in_generics( generics, @@ -774,32 +782,35 @@ impl<'tcx> ItemCtxt<'tcx> { only_self_bounds: OnlySelfBounds, assoc_name: Option<Ident>, ) -> Vec<(ty::Predicate<'tcx>, Span)> { - ast_generics - .predicates - .iter() - .filter_map(|wp| match wp { - hir::WherePredicate::BoundPredicate(bp) => Some(bp), - _ => None, - }) - .flat_map(|bp| { - let bt = if bp.is_param_bound(param_def_id.to_def_id()) { - Some(ty) - } else if !only_self_bounds.0 { - Some(self.to_ty(bp.bounded_ty)) - } else { - None - }; - let bvars = self.tcx.late_bound_vars(bp.hir_id); - - bp.bounds.iter().filter_map(move |b| bt.map(|bt| (bt, b, bvars))).filter( - |(_, b, _)| match assoc_name { - Some(assoc_name) => self.bound_defines_assoc_item(b, assoc_name), - None => true, - }, - ) - }) - .flat_map(|(bt, b, bvars)| predicates_from_bound(self, bt, b, bvars)) - .collect() + let mut bounds = Bounds::default(); + + for predicate in ast_generics.predicates { + let hir::WherePredicate::BoundPredicate(predicate) = predicate else { + continue; + }; + + let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) { + ty + } else if !only_self_bounds.0 { + self.to_ty(predicate.bounded_ty) + } else { + continue; + }; + + let bound_vars = self.tcx.late_bound_vars(predicate.hir_id); + self.astconv().add_bounds( + bound_ty, + predicate.bounds.iter().filter(|bound| { + assoc_name + .map_or(true, |assoc_name| self.bound_defines_assoc_item(bound, assoc_name)) + }), + &mut bounds, + bound_vars, + only_self_bounds, + ); + } + + bounds.predicates().collect() } #[instrument(level = "trace", skip(self))] @@ -817,19 +828,3 @@ impl<'tcx> ItemCtxt<'tcx> { } } } - -/// Converts a specific `GenericBound` from the AST into a set of -/// predicates that apply to the self type. A vector is returned -/// because this can be anywhere from zero predicates (`T: ?Sized` adds no -/// predicates) to one (`T: Foo`) to many (`T: Bar<X = i32>` adds `T: Bar` -/// and `<T as Bar>::X == i32`). -fn predicates_from_bound<'tcx>( - astconv: &dyn AstConv<'tcx>, - param_ty: Ty<'tcx>, - bound: &'tcx hir::GenericBound<'tcx>, - bound_vars: &'tcx ty::List<ty::BoundVariableKind>, -) -> Vec<(ty::Predicate<'tcx>, Span)> { - let mut bounds = Bounds::default(); - astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars); - bounds.predicates().collect() -} diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index f82169dee98..25ad1bed763 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -108,6 +108,14 @@ pub struct CopyImplOnNonAdt { } #[derive(Diagnostic)] +#[diag(hir_analysis_const_param_ty_impl_on_non_adt)] +pub struct ConstParamTyImplOnNonAdt { + #[primary_span] + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] #[diag(hir_analysis_trait_object_declared_with_no_traits, code = "E0224")] pub struct TraitObjectDeclaredWithNoTraits { #[primary_span] diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index a4b797f77f7..961457b7579 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -116,7 +116,7 @@ use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, use std::ops::Not; -use astconv::AstConv; +use astconv::{AstConv, OnlySelfBounds}; use bounds::Bounds; fluent_messages! { "../messages.ftl" } @@ -531,6 +531,7 @@ pub fn hir_trait_to_predicates<'tcx>( self_ty, &mut bounds, true, + OnlySelfBounds(false), ); bounds |
