Skip to content

Commit ae4cbbf

Browse files
committed
Propagate TraitImplHeader to hir
1 parent 7ef7c7b commit ae4cbbf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+316
-299
lines changed

compiler/rustc_ast_lowering/src/item.rs

Lines changed: 46 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -361,75 +361,30 @@ impl<'hir> LoweringContext<'_, 'hir> {
361361
// lifetime to be added, but rather a reference to a
362362
// parent lifetime.
363363
let itctx = ImplTraitContext::Universal;
364-
let (generics, (trait_ref, lowered_ty)) =
364+
let (generics, (of_trait, lowered_ty)) =
365365
self.lower_generics(ast_generics, id, itctx, |this| {
366-
let modifiers = TraitBoundModifiers {
367-
constness: BoundConstness::Never,
368-
asyncness: BoundAsyncness::Normal,
369-
// we don't use this in bound lowering
370-
polarity: BoundPolarity::Positive,
371-
};
372-
373-
let trait_ref = of_trait.as_ref().map(|of_trait| {
374-
this.lower_trait_ref(
375-
modifiers,
376-
&of_trait.trait_ref,
377-
ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
378-
)
379-
});
366+
let of_trait = of_trait
367+
.as_deref()
368+
.map(|of_trait| this.lower_trait_impl_header(of_trait));
380369

381370
let lowered_ty = this.lower_ty(
382371
ty,
383372
ImplTraitContext::Disallowed(ImplTraitPosition::ImplSelf),
384373
);
385374

386-
(trait_ref, lowered_ty)
375+
(of_trait, lowered_ty)
387376
});
388377

389378
let new_impl_items = self
390379
.arena
391380
.alloc_from_iter(impl_items.iter().map(|item| self.lower_impl_item_ref(item)));
392381

393-
// `defaultness.has_value()` is never called for an `impl`, always `true` in order
394-
// to not cause an assertion failure inside the `lower_defaultness` function.
395-
let has_val = true;
396-
let (constness, safety, polarity, defaultness, defaultness_span) = match *of_trait {
397-
Some(box TraitImplHeader {
398-
constness,
399-
safety,
400-
polarity,
401-
defaultness,
402-
trait_ref: _,
403-
}) => {
404-
let constness = self.lower_constness(constness);
405-
let safety = self.lower_safety(safety, hir::Safety::Safe);
406-
let polarity = match polarity {
407-
ImplPolarity::Positive => ImplPolarity::Positive,
408-
ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(s)),
409-
};
410-
let (defaultness, defaultness_span) =
411-
self.lower_defaultness(defaultness, has_val);
412-
(constness, safety, polarity, defaultness, defaultness_span)
413-
}
414-
None => (
415-
hir::Constness::NotConst,
416-
hir::Safety::Safe,
417-
ImplPolarity::Positive,
418-
hir::Defaultness::Final,
419-
None,
420-
),
421-
};
422-
hir::ItemKind::Impl(self.arena.alloc(hir::Impl {
423-
constness,
424-
safety,
425-
polarity,
426-
defaultness,
427-
defaultness_span,
382+
hir::ItemKind::Impl(hir::Impl {
428383
generics,
429-
of_trait: trait_ref,
384+
of_trait,
430385
self_ty: lowered_ty,
431386
items: new_impl_items,
432-
}))
387+
})
433388
}
434389
ItemKind::Trait(box Trait {
435390
constness,
@@ -1000,6 +955,44 @@ impl<'hir> LoweringContext<'_, 'hir> {
1000955
self.expr(span, hir::ExprKind::Err(guar))
1001956
}
1002957

958+
fn lower_trait_impl_header(
959+
&mut self,
960+
trait_impl_header: &TraitImplHeader,
961+
) -> &'hir hir::TraitImplHeader<'hir> {
962+
let TraitImplHeader { constness, safety, polarity, defaultness, ref trait_ref } =
963+
*trait_impl_header;
964+
let constness = self.lower_constness(constness);
965+
let safety = self.lower_safety(safety, hir::Safety::Safe);
966+
let polarity = match polarity {
967+
ImplPolarity::Positive => ImplPolarity::Positive,
968+
ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(s)),
969+
};
970+
// `defaultness.has_value()` is never called for an `impl`, always `true` in order
971+
// to not cause an assertion failure inside the `lower_defaultness` function.
972+
let has_val = true;
973+
let (defaultness, defaultness_span) = self.lower_defaultness(defaultness, has_val);
974+
let modifiers = TraitBoundModifiers {
975+
constness: BoundConstness::Never,
976+
asyncness: BoundAsyncness::Normal,
977+
// we don't use this in bound lowering
978+
polarity: BoundPolarity::Positive,
979+
};
980+
let trait_ref = self.lower_trait_ref(
981+
modifiers,
982+
trait_ref,
983+
ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
984+
);
985+
986+
&*self.arena.alloc(hir::TraitImplHeader {
987+
constness,
988+
safety,
989+
polarity,
990+
defaultness,
991+
defaultness_span,
992+
trait_ref,
993+
})
994+
}
995+
1003996
fn lower_impl_item(
1004997
&mut self,
1005998
i: &AssocItem,

compiler/rustc_hir/src/hir.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4194,7 +4194,7 @@ impl<'hir> Item<'hir> {
41944194
expect_trait_alias, (Ident, &'hir Generics<'hir>, GenericBounds<'hir>),
41954195
ItemKind::TraitAlias(ident, generics, bounds), (*ident, generics, bounds);
41964196

4197-
expect_impl, &'hir Impl<'hir>, ItemKind::Impl(imp), imp;
4197+
expect_impl, &Impl<'hir>, ItemKind::Impl(imp), imp;
41984198
}
41994199
}
42004200

@@ -4372,7 +4372,7 @@ pub enum ItemKind<'hir> {
43724372
TraitAlias(Ident, &'hir Generics<'hir>, GenericBounds<'hir>),
43734373

43744374
/// An implementation, e.g., `impl<A> Trait for Foo { .. }`.
4375-
Impl(&'hir Impl<'hir>),
4375+
Impl(Impl<'hir>),
43764376
}
43774377

43784378
/// Represents an impl block declaration.
@@ -4381,20 +4381,22 @@ pub enum ItemKind<'hir> {
43814381
/// Refer to [`ImplItem`] for an associated item within an impl block.
43824382
#[derive(Debug, Clone, Copy, HashStable_Generic)]
43834383
pub struct Impl<'hir> {
4384+
pub generics: &'hir Generics<'hir>,
4385+
pub of_trait: Option<&'hir TraitImplHeader<'hir>>,
4386+
pub self_ty: &'hir Ty<'hir>,
4387+
pub items: &'hir [ImplItemId],
4388+
}
4389+
4390+
#[derive(Debug, Clone, Copy, HashStable_Generic)]
4391+
pub struct TraitImplHeader<'hir> {
43844392
pub constness: Constness,
43854393
pub safety: Safety,
43864394
pub polarity: ImplPolarity,
43874395
pub defaultness: Defaultness,
43884396
// We do not put a `Span` in `Defaultness` because it breaks foreign crate metadata
43894397
// decoding as `Span`s cannot be decoded when a `Session` is not available.
43904398
pub defaultness_span: Option<Span>,
4391-
pub generics: &'hir Generics<'hir>,
4392-
4393-
/// The trait being implemented, if any.
4394-
pub of_trait: Option<TraitRef<'hir>>,
4395-
4396-
pub self_ty: &'hir Ty<'hir>,
4397-
pub items: &'hir [ImplItemId],
4399+
pub trait_ref: TraitRef<'hir>,
43984400
}
43994401

44004402
impl ItemKind<'_> {
@@ -4756,8 +4758,8 @@ impl<'hir> Node<'hir> {
47564758
/// Get a `hir::Impl` if the node is an impl block for the given `trait_def_id`.
47574759
pub fn impl_block_of_trait(self, trait_def_id: DefId) -> Option<&'hir Impl<'hir>> {
47584760
if let Node::Item(Item { kind: ItemKind::Impl(impl_block), .. }) = self
4759-
&& let Some(trait_ref) = impl_block.of_trait
4760-
&& let Some(trait_id) = trait_ref.trait_def_id()
4761+
&& let Some(of_trait) = impl_block.of_trait
4762+
&& let Some(trait_id) = of_trait.trait_ref.trait_def_id()
47614763
&& trait_id == trait_def_id
47624764
{
47634765
Some(impl_block)
@@ -4952,7 +4954,7 @@ mod size_asserts {
49524954
static_assert_size!(GenericArg<'_>, 16);
49534955
static_assert_size!(GenericBound<'_>, 64);
49544956
static_assert_size!(Generics<'_>, 56);
4955-
static_assert_size!(Impl<'_>, 80);
4957+
static_assert_size!(Impl<'_>, 40);
49564958
static_assert_size!(ImplItem<'_>, 96);
49574959
static_assert_size!(ImplItemKind<'_>, 40);
49584960
static_assert_size!(Item<'_>, 88);
@@ -4967,6 +4969,7 @@ mod size_asserts {
49674969
static_assert_size!(Res, 12);
49684970
static_assert_size!(Stmt<'_>, 32);
49694971
static_assert_size!(StmtKind<'_>, 16);
4972+
static_assert_size!(TraitImplHeader<'_>, 48);
49704973
static_assert_size!(TraitItem<'_>, 88);
49714974
static_assert_size!(TraitItemKind<'_>, 48);
49724975
static_assert_size!(Ty<'_>, 48);

compiler/rustc_hir/src/intravisit.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -596,21 +596,21 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
596596
try_visit!(visitor.visit_generics(generics));
597597
try_visit!(visitor.visit_enum_def(enum_definition));
598598
}
599-
ItemKind::Impl(Impl {
600-
constness: _,
601-
safety: _,
602-
defaultness: _,
603-
polarity: _,
604-
defaultness_span: _,
605-
generics,
606-
of_trait,
607-
self_ty,
608-
items,
609-
}) => {
599+
ItemKind::Impl(Impl { generics, of_trait, self_ty, items }) => {
610600
try_visit!(visitor.visit_generics(generics));
611-
visit_opt!(visitor, visit_trait_ref, of_trait);
601+
if let Some(TraitImplHeader {
602+
constness: _,
603+
safety: _,
604+
polarity: _,
605+
defaultness: _,
606+
defaultness_span: _,
607+
trait_ref,
608+
}) = of_trait
609+
{
610+
try_visit!(visitor.visit_trait_ref(trait_ref));
611+
}
612612
try_visit!(visitor.visit_ty_unambig(self_ty));
613-
walk_list!(visitor, visit_impl_item_ref, *items);
613+
walk_list!(visitor, visit_impl_item_ref, items);
614614
}
615615
ItemKind::Struct(ident, ref generics, ref struct_definition)
616616
| ItemKind::Union(ident, ref generics, ref struct_definition) => {

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 46 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -244,48 +244,48 @@ pub(super) fn check_item<'tcx>(
244244
//
245245
// won't be allowed unless there's an *explicit* implementation of `Send`
246246
// for `T`
247-
hir::ItemKind::Impl(impl_) => {
248-
let header = tcx.impl_trait_header(def_id);
249-
let is_auto = header
250-
.is_some_and(|header| tcx.trait_is_auto(header.trait_ref.skip_binder().def_id));
251-
247+
hir::ItemKind::Impl(ref impl_) => {
252248
crate::impl_wf_check::check_impl_wf(tcx, def_id)?;
253249
let mut res = Ok(());
254-
if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) {
255-
let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span);
256-
res = Err(tcx
257-
.dcx()
258-
.struct_span_err(sp, "impls of auto traits cannot be default")
259-
.with_span_labels(impl_.defaultness_span, "default because of this")
260-
.with_span_label(sp, "auto trait")
261-
.emit());
262-
}
263-
// We match on both `ty::ImplPolarity` and `ast::ImplPolarity` just to get the `!` span.
264-
match header.map(|h| h.polarity) {
265-
// `None` means this is an inherent impl
266-
Some(ty::ImplPolarity::Positive) | None => {
267-
res = res.and(check_impl(tcx, item, impl_.self_ty, &impl_.of_trait));
268-
}
269-
Some(ty::ImplPolarity::Negative) => {
270-
let ast::ImplPolarity::Negative(span) = impl_.polarity else {
271-
bug!("impl_polarity query disagrees with impl's polarity in HIR");
272-
};
273-
// FIXME(#27579): what amount of WF checking do we need for neg impls?
274-
if let hir::Defaultness::Default { .. } = impl_.defaultness {
275-
let mut spans = vec![span];
276-
spans.extend(impl_.defaultness_span);
277-
res = Err(struct_span_code_err!(
278-
tcx.dcx(),
279-
spans,
280-
E0750,
281-
"negative impls cannot be default impls"
282-
)
250+
if let Some(of_trait) = impl_.of_trait {
251+
let header = tcx.impl_trait_header(def_id).unwrap();
252+
let is_auto = tcx.trait_is_auto(header.trait_ref.skip_binder().def_id);
253+
if let (hir::Defaultness::Default { .. }, true) = (of_trait.defaultness, is_auto) {
254+
let sp = of_trait.trait_ref.path.span;
255+
res = Err(tcx
256+
.dcx()
257+
.struct_span_err(sp, "impls of auto traits cannot be default")
258+
.with_span_labels(of_trait.defaultness_span, "default because of this")
259+
.with_span_label(sp, "auto trait")
283260
.emit());
284-
}
285261
}
286-
Some(ty::ImplPolarity::Reservation) => {
287-
// FIXME: what amount of WF checking do we need for reservation impls?
262+
match header.polarity {
263+
ty::ImplPolarity::Positive => {
264+
res = res.and(check_impl(tcx, item, impl_));
265+
}
266+
ty::ImplPolarity::Negative => {
267+
let ast::ImplPolarity::Negative(span) = of_trait.polarity else {
268+
bug!("impl_polarity query disagrees with impl's polarity in HIR");
269+
};
270+
// FIXME(#27579): what amount of WF checking do we need for neg impls?
271+
if let hir::Defaultness::Default { .. } = of_trait.defaultness {
272+
let mut spans = vec![span];
273+
spans.extend(of_trait.defaultness_span);
274+
res = Err(struct_span_code_err!(
275+
tcx.dcx(),
276+
spans,
277+
E0750,
278+
"negative impls cannot be default impls"
279+
)
280+
.emit());
281+
}
282+
}
283+
ty::ImplPolarity::Reservation => {
284+
// FIXME: what amount of WF checking do we need for reservation impls?
285+
}
288286
}
287+
} else {
288+
res = res.and(check_impl(tcx, item, impl_));
289289
}
290290
res
291291
}
@@ -1258,24 +1258,23 @@ pub(crate) fn check_const_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<()
12581258
})
12591259
}
12601260

1261-
#[instrument(level = "debug", skip(tcx, hir_self_ty, hir_trait_ref))]
1261+
#[instrument(level = "debug", skip(tcx, impl_))]
12621262
fn check_impl<'tcx>(
12631263
tcx: TyCtxt<'tcx>,
12641264
item: &'tcx hir::Item<'tcx>,
1265-
hir_self_ty: &hir::Ty<'_>,
1266-
hir_trait_ref: &Option<hir::TraitRef<'_>>,
1265+
impl_: &hir::Impl<'_>,
12671266
) -> Result<(), ErrorGuaranteed> {
12681267
enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |wfcx| {
1269-
match hir_trait_ref {
1270-
Some(hir_trait_ref) => {
1268+
match impl_.of_trait {
1269+
Some(of_trait) => {
12711270
// `#[rustc_reservation_impl]` impls are not real impls and
12721271
// therefore don't need to be WF (the trait's `Self: Trait` predicate
12731272
// won't hold).
12741273
let trait_ref = tcx.impl_trait_ref(item.owner_id).unwrap().instantiate_identity();
12751274
// Avoid bogus "type annotations needed `Foo: Bar`" errors on `impl Bar for Foo` in case
12761275
// other `Foo` impls are incoherent.
12771276
tcx.ensure_ok().coherent_trait(trait_ref.def_id)?;
1278-
let trait_span = hir_trait_ref.path.span;
1277+
let trait_span = of_trait.trait_ref.path.span;
12791278
let trait_ref = wfcx.deeply_normalize(
12801279
trait_span,
12811280
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
@@ -1299,12 +1298,12 @@ fn check_impl<'tcx>(
12991298
if let Some(pred) = obligation.predicate.as_trait_clause()
13001299
&& pred.skip_binder().self_ty() == trait_ref.self_ty()
13011300
{
1302-
obligation.cause.span = hir_self_ty.span;
1301+
obligation.cause.span = impl_.self_ty.span;
13031302
}
13041303
if let Some(pred) = obligation.predicate.as_projection_clause()
13051304
&& pred.skip_binder().self_ty() == trait_ref.self_ty()
13061305
{
1307-
obligation.cause.span = hir_self_ty.span;
1306+
obligation.cause.span = impl_.self_ty.span;
13081307
}
13091308
}
13101309

@@ -1321,7 +1320,7 @@ fn check_impl<'tcx>(
13211320
wfcx.register_obligation(Obligation::new(
13221321
tcx,
13231322
ObligationCause::new(
1324-
hir_self_ty.span,
1323+
impl_.self_ty.span,
13251324
wfcx.body_def_id,
13261325
ObligationCauseCode::WellFormed(None),
13271326
),
@@ -1342,7 +1341,7 @@ fn check_impl<'tcx>(
13421341
self_ty,
13431342
);
13441343
wfcx.register_wf_obligation(
1345-
hir_self_ty.span,
1344+
impl_.self_ty.span,
13461345
Some(WellFormedLoc::Ty(item.hir_id().expect_owner().def_id)),
13471346
self_ty.into(),
13481347
);

0 commit comments

Comments
 (0)