diff options
Diffstat (limited to 'compiler/rustc_hir_analysis')
| -rw-r--r-- | compiler/rustc_hir_analysis/src/astconv/mod.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/astconv/object_safety.rs | 80 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/check.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/wfcheck.rs | 50 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/coherence/builtin.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/coherence/mod.rs | 9 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/coherence/unsafety.rs | 3 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/collect.rs | 11 |
8 files changed, 95 insertions, 98 deletions
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index b8cf72c2c73..325342d653d 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1612,10 +1612,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .any(|impl_def_id| { let impl_header = tcx.impl_trait_header(impl_def_id); impl_header.is_some_and(|header| { - let header = header.instantiate( + let trait_ref = header.trait_ref.instantiate( tcx, infcx.fresh_args_for_item(DUMMY_SP, impl_def_id), ); + let value = tcx.fold_regions(qself_ty, |_, _| tcx.lifetimes.re_erased); // FIXME: Don't bother dealing with non-lifetime binders here... if value.has_escaping_bound_vars() { @@ -1624,7 +1625,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { infcx .can_eq( ty::ParamEnv::empty(), - header.trait_ref.self_ty(), + trait_ref.self_ty(), value, ) && header.polarity != ty::ImplPolarity::Negative }) @@ -1677,9 +1678,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { .filter(|header| { // Consider only accessible traits tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx) - && header.skip_binder().polarity != ty::ImplPolarity::Negative + && header.polarity != ty::ImplPolarity::Negative }) - .map(|header| header.instantiate_identity().trait_ref.self_ty()) + .map(|header| header.trait_ref.instantiate_identity().self_ty()) // We don't care about blanket impls. .filter(|self_ty| !self_ty.has_non_region_param()) .map(|self_ty| tcx.erase_regions(self_ty).to_string()) diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index 7705445ffaa..b9543c7a29b 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -45,10 +45,9 @@ 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), + // True so we don't populate `bounds` with associated type bounds, even + // though they're disallowed from object types. + OnlySelfBounds(true), ) { potential_assoc_types.extend(cur_potential_assoc_types); } @@ -83,9 +82,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let expanded_traits = traits::expand_trait_aliases(tcx, trait_bounds.iter().map(|&(a, b)| (a, b))); - let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = expanded_traits - .filter(|i| i.trait_ref().self_ty().skip_binder() == dummy_self) - .partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); + let (mut auto_traits, regular_traits): (Vec<_>, Vec<_>) = + expanded_traits.partition(|i| tcx.trait_is_auto(i.trait_ref().def_id())); if regular_traits.len() > 1 { let first_trait = ®ular_traits[0]; let additional_trait = ®ular_traits[1]; @@ -158,7 +156,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { for (base_trait_ref, span) in regular_traits_refs_spans { let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx); - for pred in traits::elaborate(tcx, [base_pred]) { + for pred in traits::elaborate(tcx, [base_pred]).filter_only_self() { debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred); let bound_predicate = pred.kind(); @@ -312,45 +310,39 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }) }); - let existential_projections = projection_bounds - .iter() - // We filter out traits that don't have `Self` as their self type above, - // we need to do the same for projections. - .filter(|(bound, _)| bound.skip_binder().self_ty() == dummy_self) - .map(|(bound, _)| { - bound.map_bound(|mut b| { - assert_eq!(b.projection_ty.self_ty(), dummy_self); + let existential_projections = projection_bounds.iter().map(|(bound, _)| { + bound.map_bound(|mut b| { + assert_eq!(b.projection_ty.self_ty(), dummy_self); - // Like for trait refs, verify that `dummy_self` did not leak inside default type - // parameters. - let references_self = b.projection_ty.args.iter().skip(1).any(|arg| { - if arg.walk().any(|arg| arg == dummy_self.into()) { - return true; - } - false - }); - if references_self { - let guar = tcx.dcx().span_delayed_bug( - span, - "trait object projection bounds reference `Self`", - ); - let args: Vec<_> = b - .projection_ty - .args - .iter() - .map(|arg| { - if arg.walk().any(|arg| arg == dummy_self.into()) { - return Ty::new_error(tcx, guar).into(); - } - arg - }) - .collect(); - b.projection_ty.args = tcx.mk_args(&args); + // Like for trait refs, verify that `dummy_self` did not leak inside default type + // parameters. + let references_self = b.projection_ty.args.iter().skip(1).any(|arg| { + if arg.walk().any(|arg| arg == dummy_self.into()) { + return true; } + false + }); + if references_self { + let guar = tcx + .dcx() + .span_delayed_bug(span, "trait object projection bounds reference `Self`"); + let args: Vec<_> = b + .projection_ty + .args + .iter() + .map(|arg| { + if arg.walk().any(|arg| arg == dummy_self.into()) { + return Ty::new_error(tcx, guar).into(); + } + arg + }) + .collect(); + b.projection_ty.args = tcx.mk_args(&args); + } - ty::ExistentialProjection::erase_self_ty(tcx, b) - }) - }); + ty::ExistentialProjection::erase_self_ty(tcx, b) + }) + }); let regular_trait_predicates = existential_trait_refs .map(|trait_ref| trait_ref.map_bound(ty::ExistentialPredicate::Trait)); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 845bbdca96a..748571c12b3 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -530,11 +530,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { } DefKind::Impl { of_trait } => { if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) { - check_impl_items_against_trait( - tcx, - def_id, - impl_trait_header.instantiate_identity(), - ); + check_impl_items_against_trait(tcx, def_id, impl_trait_header); check_on_unimplemented(tcx, def_id); } } @@ -725,10 +721,11 @@ fn check_impl_items_against_trait<'tcx>( impl_id: LocalDefId, impl_trait_header: ty::ImplTraitHeader<'tcx>, ) { + let trait_ref = impl_trait_header.trait_ref.instantiate_identity(); // If the trait reference itself is erroneous (so the compilation is going // to fail), skip checking the items here -- the `impl_item` table in `tcx` // isn't populated for such impls. - if impl_trait_header.references_error() { + if trait_ref.references_error() { return; } @@ -752,7 +749,7 @@ fn check_impl_items_against_trait<'tcx>( } } - let trait_def = tcx.trait_def(impl_trait_header.trait_ref.def_id); + let trait_def = tcx.trait_def(trait_ref.def_id); for &impl_item in impl_item_refs { let ty_impl_item = tcx.associated_item(impl_item); @@ -771,10 +768,10 @@ fn check_impl_items_against_trait<'tcx>( )); } ty::AssocKind::Fn => { - compare_impl_method(tcx, ty_impl_item, ty_trait_item, impl_trait_header.trait_ref); + compare_impl_method(tcx, ty_impl_item, ty_trait_item, trait_ref); } ty::AssocKind::Type => { - compare_impl_ty(tcx, ty_impl_item, ty_trait_item, impl_trait_header.trait_ref); + compare_impl_ty(tcx, ty_impl_item, ty_trait_item, trait_ref); } } @@ -794,7 +791,7 @@ fn check_impl_items_against_trait<'tcx>( let mut must_implement_one_of: Option<&[Ident]> = trait_def.must_implement_one_of.as_deref(); - for &trait_item_id in tcx.associated_item_def_ids(impl_trait_header.trait_ref.def_id) { + for &trait_item_id in tcx.associated_item_def_ids(trait_ref.def_id) { let leaf_def = ancestors.leaf_def(tcx, trait_item_id); let is_implemented = leaf_def @@ -872,7 +869,7 @@ fn check_impl_items_against_trait<'tcx>( if let Some(missing_items) = must_implement_one_of { let attr_span = tcx - .get_attr(impl_trait_header.trait_ref.def_id, sym::rustc_must_implement_one_of) + .get_attr(trait_ref.def_id, sym::rustc_must_implement_one_of) .map(|attr| attr.span); missing_items_must_implement_one_of_err( diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 8d457da89e8..ae7ea271c56 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -247,7 +247,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() hir::ItemKind::Impl(impl_) => { let header = tcx.impl_trait_header(def_id); let is_auto = header - .is_some_and(|header| tcx.trait_is_auto(header.skip_binder().trait_ref.def_id)); + .is_some_and(|header| tcx.trait_is_auto(header.trait_ref.skip_binder().def_id)); crate::impl_wf_check::check_impl_wf(tcx, def_id)?; let mut res = Ok(()); @@ -261,7 +261,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() .emit()); } // We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span. - match header.map(|h| h.skip_binder().polarity) { + match header.map(|h| h.polarity) { // `None` means this is an inherent impl Some(ty::ImplPolarity::Positive) | None => { res = res.and(check_impl(tcx, item, impl_.self_ty, &impl_.of_trait)); @@ -298,31 +298,31 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() hir::ItemKind::Const(ty, ..) => { check_item_type(tcx, def_id, ty.span, UnsizedHandling::Forbid) } - hir::ItemKind::Struct(_, ast_generics) => { + hir::ItemKind::Struct(_, hir_generics) => { let res = check_type_defn(tcx, item, false); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } - hir::ItemKind::Union(_, ast_generics) => { + hir::ItemKind::Union(_, hir_generics) => { let res = check_type_defn(tcx, item, true); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } - hir::ItemKind::Enum(_, ast_generics) => { + hir::ItemKind::Enum(_, hir_generics) => { let res = check_type_defn(tcx, item, true); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } hir::ItemKind::Trait(..) => check_trait(tcx, item), hir::ItemKind::TraitAlias(..) => check_trait(tcx, item), // `ForeignItem`s are handled separately. hir::ItemKind::ForeignMod { .. } => Ok(()), - hir::ItemKind::TyAlias(hir_ty, ast_generics) => { + hir::ItemKind::TyAlias(hir_ty, hir_generics) => { if tcx.type_alias_is_lazy(item.owner_id) { // Bounds of lazy type aliases and of eager ones that contain opaque types are respected. // E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`. let res = check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow); - check_variances_for_type_defn(tcx, item, ast_generics); + check_variances_for_type_defn(tcx, item, hir_generics); res } else { Ok(()) @@ -1277,16 +1277,16 @@ fn check_item_type( }) } -#[instrument(level = "debug", skip(tcx, ast_self_ty, ast_trait_ref))] +#[instrument(level = "debug", skip(tcx, hir_self_ty, hir_trait_ref))] fn check_impl<'tcx>( tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>, - ast_self_ty: &hir::Ty<'_>, - ast_trait_ref: &Option<hir::TraitRef<'_>>, + hir_self_ty: &hir::Ty<'_>, + hir_trait_ref: &Option<hir::TraitRef<'_>>, ) -> Result<(), ErrorGuaranteed> { enter_wf_checking_ctxt(tcx, item.span, item.owner_id.def_id, |wfcx| { - match ast_trait_ref { - Some(ast_trait_ref) => { + match hir_trait_ref { + Some(hir_trait_ref) => { // `#[rustc_reservation_impl]` impls are not real impls and // therefore don't need to be WF (the trait's `Self: Trait` predicate // won't hold). @@ -1294,8 +1294,9 @@ fn check_impl<'tcx>( // Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case // other `Foo` impls are incoherent. tcx.ensure().coherent_trait(trait_ref.def_id)?; + let trait_span = hir_trait_ref.path.span; let trait_ref = wfcx.normalize( - ast_trait_ref.path.span, + trait_span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), trait_ref, ); @@ -1306,14 +1307,23 @@ fn check_impl<'tcx>( wfcx.param_env, wfcx.body_def_id, trait_pred, - ast_trait_ref.path.span, + trait_span, item, ); for obligation in &mut obligations { + if obligation.cause.span != trait_span { + // We already have a better span. + continue; + } if let Some(pred) = obligation.predicate.to_opt_poly_trait_pred() - && pred.self_ty().skip_binder() == trait_ref.self_ty() + && pred.skip_binder().self_ty() == trait_ref.self_ty() + { + obligation.cause.span = hir_self_ty.span; + } + if let Some(pred) = obligation.predicate.to_opt_poly_projection_pred() + && pred.skip_binder().self_ty() == trait_ref.self_ty() { - obligation.cause.span = ast_self_ty.span; + obligation.cause.span = hir_self_ty.span; } } debug!(?obligations); @@ -1327,7 +1337,7 @@ fn check_impl<'tcx>( self_ty, ); wfcx.register_wf_obligation( - ast_self_ty.span, + hir_self_ty.span, Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)), self_ty.into(), ); diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index 6c3a9b747ef..8d8b13d6cb3 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -25,7 +25,7 @@ use rustc_trait_selection::traits::ObligationCtxt; use rustc_trait_selection::traits::{self, ObligationCause}; use std::collections::BTreeMap; -pub fn check_trait<'tcx>( +pub(super) fn check_trait<'tcx>( tcx: TyCtxt<'tcx>, trait_def_id: DefId, impl_def_id: LocalDefId, @@ -66,10 +66,9 @@ impl<'tcx> Checker<'tcx> { fn visit_implementation_of_drop(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { let tcx = checker.tcx; - let header = checker.impl_header; let impl_did = checker.impl_def_id; // Destructors only work on local ADT types. - match header.trait_ref.self_ty().kind() { + match checker.impl_header.trait_ref.instantiate_identity().self_ty().kind() { ty::Adt(def, _) if def.did().is_local() => return Ok(()), ty::Error(_) => return Ok(()), _ => {} @@ -86,7 +85,7 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran let impl_did = checker.impl_def_id; debug!("visit_implementation_of_copy: impl_did={:?}", impl_did); - let self_type = impl_header.trait_ref.self_ty(); + let self_type = impl_header.trait_ref.instantiate_identity().self_ty(); debug!("visit_implementation_of_copy: self_type={:?} (bound)", self_type); let param_env = tcx.param_env(impl_did); @@ -120,7 +119,7 @@ fn visit_implementation_of_const_param_ty(checker: &Checker<'_>) -> Result<(), E let tcx = checker.tcx; let header = checker.impl_header; let impl_did = checker.impl_def_id; - let self_type = header.trait_ref.self_ty(); + let self_type = header.trait_ref.instantiate_identity().self_ty(); assert!(!self_type.has_escaping_bound_vars()); let param_env = tcx.param_env(impl_did); @@ -157,9 +156,8 @@ fn visit_implementation_of_coerce_unsized(checker: &Checker<'_>) -> Result<(), E fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<(), ErrorGuaranteed> { let tcx = checker.tcx; - let header = checker.impl_header; let impl_did = checker.impl_def_id; - let trait_ref = header.trait_ref; + let trait_ref = checker.impl_header.trait_ref.instantiate_identity(); debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did); let span = tcx.def_span(impl_did); diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index d6281fa08f7..fc7a73e12be 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -134,11 +134,12 @@ fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> let mut res = tcx.ensure().specialization_graph_of(def_id); for &impl_def_id in impls { - let trait_header = tcx.impl_trait_header(impl_def_id).unwrap().instantiate_identity(); - let trait_def = tcx.trait_def(trait_header.trait_ref.def_id); + let trait_header = tcx.impl_trait_header(impl_def_id).unwrap(); + let trait_ref = trait_header.trait_ref.instantiate_identity(); + let trait_def = tcx.trait_def(trait_ref.def_id); - res = res.and(check_impl(tcx, impl_def_id, trait_header.trait_ref, trait_def)); - res = res.and(check_object_overlap(tcx, impl_def_id, trait_header.trait_ref)); + res = res.and(check_impl(tcx, impl_def_id, trait_ref, trait_def)); + res = res.and(check_object_overlap(tcx, impl_def_id, trait_ref)); res = res.and(unsafety::check_item(tcx, impl_def_id, trait_header, trait_def)); res = res.and(tcx.ensure().orphan_check_impl(impl_def_id)); diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index 53a5ada4105..13ce4f07593 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -13,9 +13,10 @@ pub(super) fn check_item( trait_header: ImplTraitHeader<'_>, trait_def: &TraitDef, ) -> Result<(), ErrorGuaranteed> { - let trait_ref = trait_header.trait_ref; let unsafe_attr = tcx.generics_of(def_id).params.iter().find(|p| p.pure_wrt_drop).map(|_| "may_dangle"); + let trait_ref = trait_header.trait_ref.instantiate_identity(); + match (trait_def.unsafety, unsafe_attr, trait_header.unsafety, trait_header.polarity) { (Unsafety::Normal, None, Unsafety::Unsafe, Positive | Reservation) => { let span = tcx.def_span(def_id); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 2cc37651ef5..e1704ffc8bf 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1519,10 +1519,7 @@ fn suggest_impl_trait<'tcx>( None } -fn impl_trait_header( - tcx: TyCtxt<'_>, - def_id: LocalDefId, -) -> Option<ty::EarlyBinder<ty::ImplTraitHeader<'_>>> { +fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTraitHeader<'_>> { let icx = ItemCtxt::new(tcx, def_id); let item = tcx.hir().expect_item(def_id); let impl_ = item.expect_impl(); @@ -1558,11 +1555,11 @@ fn impl_trait_header( } else { icx.astconv().instantiate_mono_trait_ref(ast_trait_ref, selfty) }; - ty::EarlyBinder::bind(ty::ImplTraitHeader { - trait_ref, + ty::ImplTraitHeader { + trait_ref: ty::EarlyBinder::bind(trait_ref), unsafety: impl_.unsafety, polarity: polarity_of_impl(tcx, def_id, impl_, item.span) - }) + } }) } |
