Skip to content

Commit 030354f

Browse files
committed
Factor out shared code for lowering assoc item paths
1 parent ece9e77 commit 030354f

File tree

4 files changed

+88
-105
lines changed

4 files changed

+88
-105
lines changed

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 42 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ use tracing::{debug, instrument};
4646

4747
use crate::check::intrinsic::intrinsic_operation_unsafety;
4848
use crate::errors;
49+
use crate::hir_ty_lowering::errors::assoc_kind_str;
4950
use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer, RegionInferReason};
5051

5152
pub(crate) mod dump;
@@ -468,84 +469,15 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
468469
item_segment: &hir::PathSegment<'tcx>,
469470
poly_trait_ref: ty::PolyTraitRef<'tcx>,
470471
) -> Ty<'tcx> {
471-
if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
472-
let item_args = self.lowerer().lower_generic_args_of_assoc_item(
473-
span,
474-
item_def_id,
475-
item_segment,
476-
trait_ref.args,
477-
);
478-
Ty::new_projection_from_args(self.tcx(), item_def_id, item_args)
479-
} else {
480-
// There are no late-bound regions; we can just ignore the binder.
481-
let (mut mpart_sugg, mut inferred_sugg) = (None, None);
482-
let mut bound = String::new();
483-
484-
match self.node() {
485-
hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
486-
let item = self
487-
.tcx
488-
.hir()
489-
.expect_item(self.tcx.hir().get_parent_item(self.hir_id()).def_id);
490-
match &item.kind {
491-
hir::ItemKind::Enum(_, generics)
492-
| hir::ItemKind::Struct(_, generics)
493-
| hir::ItemKind::Union(_, generics) => {
494-
let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics);
495-
let (lt_sp, sugg) = match generics.params {
496-
[] => (generics.span, format!("<{lt_name}>")),
497-
[bound, ..] => (bound.span.shrink_to_lo(), format!("{lt_name}, ")),
498-
};
499-
mpart_sugg = Some(errors::AssociatedItemTraitUninferredGenericParamsMultipartSuggestion {
500-
fspan: lt_sp,
501-
first: sugg,
502-
sspan: span.with_hi(item_segment.ident.span.lo()),
503-
second: format!(
504-
"{}::",
505-
// Replace the existing lifetimes with a new named lifetime.
506-
self.tcx.instantiate_bound_regions_uncached(
507-
poly_trait_ref,
508-
|_| {
509-
ty::Region::new_early_param(self.tcx, ty::EarlyParamRegion {
510-
index: 0,
511-
name: Symbol::intern(&lt_name),
512-
})
513-
}
514-
),
515-
),
516-
});
517-
}
518-
_ => {}
519-
}
520-
}
521-
hir::Node::Item(hir::Item {
522-
kind:
523-
hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..),
524-
..
525-
}) => {}
526-
hir::Node::Item(_)
527-
| hir::Node::ForeignItem(_)
528-
| hir::Node::TraitItem(_)
529-
| hir::Node::ImplItem(_) => {
530-
inferred_sugg = Some(span.with_hi(item_segment.ident.span.lo()));
531-
bound = format!(
532-
"{}::",
533-
// Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`.
534-
self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
535-
);
536-
}
537-
_ => {}
538-
}
539-
Ty::new_error(
540-
self.tcx(),
541-
self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
542-
span,
543-
inferred_sugg,
544-
bound,
545-
mpart_sugg,
546-
what: "type",
547-
}),
548-
)
472+
match self.lower_assoc_shared(
473+
span,
474+
item_def_id,
475+
item_segment,
476+
poly_trait_ref,
477+
ty::AssocKind::Type,
478+
) {
479+
Ok((def_id, args)) => Ty::new_projection_from_args(self.tcx(), def_id, args),
480+
Err(witness) => Ty::new_error(self.tcx(), witness),
549481
}
550482
}
551483

@@ -556,15 +488,37 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
556488
item_segment: &hir::PathSegment<'tcx>,
557489
poly_trait_ref: ty::PolyTraitRef<'tcx>,
558490
) -> Const<'tcx> {
491+
match self.lower_assoc_shared(
492+
span,
493+
item_def_id,
494+
item_segment,
495+
poly_trait_ref,
496+
ty::AssocKind::Const,
497+
) {
498+
Ok((def_id, args)) => {
499+
let uv = ty::UnevaluatedConst::new(def_id, args);
500+
Const::new_unevaluated(self.tcx(), uv)
501+
}
502+
Err(witness) => Const::new_error(self.tcx(), witness),
503+
}
504+
}
505+
506+
fn lower_assoc_shared(
507+
&self,
508+
span: Span,
509+
item_def_id: DefId,
510+
item_segment: &rustc_hir::PathSegment<'tcx>,
511+
poly_trait_ref: ty::PolyTraitRef<'tcx>,
512+
kind: ty::AssocKind,
513+
) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> {
559514
if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
560515
let item_args = self.lowerer().lower_generic_args_of_assoc_item(
561516
span,
562517
item_def_id,
563518
item_segment,
564519
trait_ref.args,
565520
);
566-
let uv = ty::UnevaluatedConst::new(item_def_id, item_args);
567-
Const::new_unevaluated(self.tcx(), uv)
521+
Ok((item_def_id, item_args))
568522
} else {
569523
// There are no late-bound regions; we can just ignore the binder.
570524
let (mut mpart_sugg, mut inferred_sugg) = (None, None);
@@ -625,16 +579,14 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
625579
}
626580
_ => {}
627581
}
628-
Const::new_error(
629-
self.tcx(),
630-
self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
631-
span,
632-
inferred_sugg,
633-
bound,
634-
mpart_sugg,
635-
what: "const",
636-
}),
637-
)
582+
583+
Err(self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
584+
span,
585+
inferred_sugg,
586+
bound,
587+
mpart_sugg,
588+
what: assoc_kind_str(kind),
589+
}))
638590
}
639591
}
640592

compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1608,7 +1608,7 @@ fn generics_args_err_extend<'a>(
16081608
}
16091609
}
16101610

1611-
pub(super) fn assoc_kind_str(kind: ty::AssocKind) -> &'static str {
1611+
pub(crate) fn assoc_kind_str(kind: ty::AssocKind) -> &'static str {
16121612
match kind {
16131613
ty::AssocKind::Fn => "function",
16141614
ty::AssocKind::Const => "constant",

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,18 @@ pub trait HirTyLowerer<'tcx> {
179179
poly_trait_ref: ty::PolyTraitRef<'tcx>,
180180
) -> Const<'tcx>;
181181

182+
/// Helper function; use [`Self::lower_assoc_ty`] or [`Self::lower_assoc_const`] instead.
183+
///
184+
/// The logic for lowering associated items that is the same between types and consts.
185+
fn lower_assoc_shared(
186+
&self,
187+
span: Span,
188+
item_def_id: DefId,
189+
item_segment: &hir::PathSegment<'tcx>,
190+
poly_trait_ref: ty::PolyTraitRef<'tcx>,
191+
kind: ty::AssocKind,
192+
) -> Result<(DefId, GenericArgsRef<'tcx>), ErrorGuaranteed>;
193+
182194
fn lower_fn_sig(
183195
&self,
184196
decl: &hir::FnDecl<'tcx>,

compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use rustc_infer::infer;
1717
use rustc_infer::traits::Obligation;
1818
use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
1919
use rustc_session::Session;
20-
use rustc_span::{self, DUMMY_SP, Ident, Span, sym};
20+
use rustc_span::{self, DUMMY_SP, ErrorGuaranteed, Ident, Span, sym};
2121
use rustc_trait_selection::error_reporting::TypeErrCtxt;
2222
use rustc_trait_selection::error_reporting::infer::sub_relations::SubRelations;
2323
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
@@ -315,20 +315,16 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
315315
item_segment: &hir::PathSegment<'tcx>,
316316
poly_trait_ref: ty::PolyTraitRef<'tcx>,
317317
) -> Ty<'tcx> {
318-
let trait_ref = self.instantiate_binder_with_fresh_vars(
319-
span,
320-
infer::BoundRegionConversionTime::AssocTypeProjection(item_def_id),
321-
poly_trait_ref,
322-
);
323-
324-
let item_args = self.lowerer().lower_generic_args_of_assoc_item(
318+
match self.lower_assoc_shared(
325319
span,
326320
item_def_id,
327321
item_segment,
328-
trait_ref.args,
329-
);
330-
331-
Ty::new_projection_from_args(self.tcx(), item_def_id, item_args)
322+
poly_trait_ref,
323+
ty::AssocKind::Type,
324+
) {
325+
Ok((def_id, args)) => Ty::new_projection_from_args(self.tcx(), def_id, args),
326+
Err(witness) => Ty::new_error(self.tcx(), witness),
327+
}
332328
}
333329

334330
fn lower_assoc_const(
@@ -338,9 +334,32 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
338334
item_segment: &hir::PathSegment<'tcx>,
339335
poly_trait_ref: ty::PolyTraitRef<'tcx>,
340336
) -> Const<'tcx> {
337+
match self.lower_assoc_shared(
338+
span,
339+
item_def_id,
340+
item_segment,
341+
poly_trait_ref,
342+
ty::AssocKind::Const,
343+
) {
344+
Ok((def_id, args)) => {
345+
let uv = ty::UnevaluatedConst::new(def_id, args);
346+
Const::new_unevaluated(self.tcx(), uv)
347+
}
348+
Err(witness) => Const::new_error(self.tcx(), witness),
349+
}
350+
}
351+
352+
fn lower_assoc_shared(
353+
&self,
354+
span: Span,
355+
item_def_id: DefId,
356+
item_segment: &rustc_hir::PathSegment<'tcx>,
357+
poly_trait_ref: ty::PolyTraitRef<'tcx>,
358+
_kind: ty::AssocKind,
359+
) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> {
341360
let trait_ref = self.instantiate_binder_with_fresh_vars(
342361
span,
343-
// FIXME(mgca): this should be assoc const not assoc type
362+
// FIXME(mgca): this should be assoc const if that is the `kind`
344363
infer::BoundRegionConversionTime::AssocTypeProjection(item_def_id),
345364
poly_trait_ref,
346365
);
@@ -352,7 +371,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> {
352371
trait_ref.args,
353372
);
354373

355-
Const::new_unevaluated(self.tcx(), ty::UnevaluatedConst::new(item_def_id, item_args))
374+
Ok((item_def_id, item_args))
356375
}
357376

358377
fn probe_adt(&self, span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {

0 commit comments

Comments
 (0)