Skip to content

Commit 3e6de40

Browse files
committed
Factor out shared code for lowering assoc item paths
1 parent 764e46b commit 3e6de40

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;
@@ -451,84 +452,15 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
451452
item_segment: &hir::PathSegment<'tcx>,
452453
poly_trait_ref: ty::PolyTraitRef<'tcx>,
453454
) -> Ty<'tcx> {
454-
if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
455-
let item_args = self.lowerer().lower_generic_args_of_assoc_item(
456-
span,
457-
item_def_id,
458-
item_segment,
459-
trait_ref.args,
460-
);
461-
Ty::new_projection_from_args(self.tcx(), item_def_id, item_args)
462-
} else {
463-
// There are no late-bound regions; we can just ignore the binder.
464-
let (mut mpart_sugg, mut inferred_sugg) = (None, None);
465-
let mut bound = String::new();
466-
467-
match self.node() {
468-
hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
469-
let item = self
470-
.tcx
471-
.hir()
472-
.expect_item(self.tcx.hir().get_parent_item(self.hir_id()).def_id);
473-
match &item.kind {
474-
hir::ItemKind::Enum(_, generics)
475-
| hir::ItemKind::Struct(_, generics)
476-
| hir::ItemKind::Union(_, generics) => {
477-
let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics);
478-
let (lt_sp, sugg) = match generics.params {
479-
[] => (generics.span, format!("<{lt_name}>")),
480-
[bound, ..] => (bound.span.shrink_to_lo(), format!("{lt_name}, ")),
481-
};
482-
mpart_sugg = Some(errors::AssociatedItemTraitUninferredGenericParamsMultipartSuggestion {
483-
fspan: lt_sp,
484-
first: sugg,
485-
sspan: span.with_hi(item_segment.ident.span.lo()),
486-
second: format!(
487-
"{}::",
488-
// Replace the existing lifetimes with a new named lifetime.
489-
self.tcx.instantiate_bound_regions_uncached(
490-
poly_trait_ref,
491-
|_| {
492-
ty::Region::new_early_param(self.tcx, ty::EarlyParamRegion {
493-
index: 0,
494-
name: Symbol::intern(&lt_name),
495-
})
496-
}
497-
),
498-
),
499-
});
500-
}
501-
_ => {}
502-
}
503-
}
504-
hir::Node::Item(hir::Item {
505-
kind:
506-
hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..),
507-
..
508-
}) => {}
509-
hir::Node::Item(_)
510-
| hir::Node::ForeignItem(_)
511-
| hir::Node::TraitItem(_)
512-
| hir::Node::ImplItem(_) => {
513-
inferred_sugg = Some(span.with_hi(item_segment.ident.span.lo()));
514-
bound = format!(
515-
"{}::",
516-
// Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`.
517-
self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
518-
);
519-
}
520-
_ => {}
521-
}
522-
Ty::new_error(
523-
self.tcx(),
524-
self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
525-
span,
526-
inferred_sugg,
527-
bound,
528-
mpart_sugg,
529-
what: "type",
530-
}),
531-
)
455+
match self.lower_assoc_shared(
456+
span,
457+
item_def_id,
458+
item_segment,
459+
poly_trait_ref,
460+
ty::AssocKind::Type,
461+
) {
462+
Ok((def_id, args)) => Ty::new_projection_from_args(self.tcx(), def_id, args),
463+
Err(witness) => Ty::new_error(self.tcx(), witness),
532464
}
533465
}
534466

@@ -539,15 +471,37 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
539471
item_segment: &hir::PathSegment<'tcx>,
540472
poly_trait_ref: ty::PolyTraitRef<'tcx>,
541473
) -> Const<'tcx> {
474+
match self.lower_assoc_shared(
475+
span,
476+
item_def_id,
477+
item_segment,
478+
poly_trait_ref,
479+
ty::AssocKind::Const,
480+
) {
481+
Ok((def_id, args)) => {
482+
let uv = ty::UnevaluatedConst::new(def_id, args);
483+
Const::new_unevaluated(self.tcx(), uv)
484+
}
485+
Err(witness) => Const::new_error(self.tcx(), witness),
486+
}
487+
}
488+
489+
fn lower_assoc_shared(
490+
&self,
491+
span: Span,
492+
item_def_id: DefId,
493+
item_segment: &rustc_hir::PathSegment<'tcx>,
494+
poly_trait_ref: ty::PolyTraitRef<'tcx>,
495+
kind: ty::AssocKind,
496+
) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> {
542497
if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
543498
let item_args = self.lowerer().lower_generic_args_of_assoc_item(
544499
span,
545500
item_def_id,
546501
item_segment,
547502
trait_ref.args,
548503
);
549-
let uv = ty::UnevaluatedConst::new(item_def_id, item_args);
550-
Const::new_unevaluated(self.tcx(), uv)
504+
Ok((item_def_id, item_args))
551505
} else {
552506
// There are no late-bound regions; we can just ignore the binder.
553507
let (mut mpart_sugg, mut inferred_sugg) = (None, None);
@@ -608,16 +562,14 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
608562
}
609563
_ => {}
610564
}
611-
Const::new_error(
612-
self.tcx(),
613-
self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
614-
span,
615-
inferred_sugg,
616-
bound,
617-
mpart_sugg,
618-
what: "const",
619-
}),
620-
)
565+
566+
Err(self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
567+
span,
568+
inferred_sugg,
569+
bound,
570+
mpart_sugg,
571+
what: assoc_kind_str(kind),
572+
}))
621573
}
622574
}
623575

compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1590,7 +1590,7 @@ fn generics_args_err_extend<'a>(
15901590
}
15911591
}
15921592

1593-
pub(super) fn assoc_kind_str(kind: ty::AssocKind) -> &'static str {
1593+
pub(crate) fn assoc_kind_str(kind: ty::AssocKind) -> &'static str {
15941594
match kind {
15951595
ty::AssocKind::Fn => "function",
15961596
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)