Skip to content

HIR ty lowering: Clean up & refactor the lowering of type-relative paths #140218

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ hir_analysis_assoc_kind_mismatch = expected {$expected}, found {$got}

hir_analysis_assoc_kind_mismatch_wrap_in_braces_sugg = consider adding braces here

hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated {$what} of a trait with uninferred generic parameters
hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the {$what} of a trait with uninferred generic parameters
.suggestion = use a fully qualified path with inferred lifetimes

hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ use rustc_trait_selection::traits::ObligationCtxt;
use tracing::{debug, instrument};

use crate::errors;
use crate::hir_ty_lowering::errors::assoc_tag_str;
use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer, RegionInferReason};

pub(crate) mod dump;
Expand Down Expand Up @@ -444,13 +443,12 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
self.tcx.at(span).type_param_predicates((self.item_def_id, def_id, assoc_ident))
}

fn lower_assoc_shared(
fn lower_assoc_item_path(
&self,
span: Span,
item_def_id: DefId,
item_segment: &rustc_hir::PathSegment<'tcx>,
poly_trait_ref: ty::PolyTraitRef<'tcx>,
assoc_tag: ty::AssocTag,
) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> {
if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
let item_args = self.lowerer().lower_generic_args_of_assoc_item(
Expand Down Expand Up @@ -525,7 +523,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
inferred_sugg,
bound,
mpart_sugg,
what: assoc_tag_str(assoc_tag),
what: self.tcx.def_descr(item_def_id),
}))
}
}
Expand Down
147 changes: 39 additions & 108 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_errors::codes::*;
use rustc_errors::struct_span_code_err;
use rustc_hir as hir;
use rustc_hir::AmbigArg;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::{AmbigArg, HirId};
use rustc_middle::bug;
use rustc_middle::ty::{
self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
Expand Down Expand Up @@ -309,7 +309,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
false => "`?Sized`",
};
// There was a `?Trait` bound, but it was neither `?Sized` nor `experimental_default_bounds`.
tcx.dcx().span_err(
self.dcx().span_err(
unbound.span,
format!(
"relaxing a default bound only does something for {}; \
Expand Down Expand Up @@ -675,7 +675,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {

// Good error for `where Trait::method(..): Send`.
let Some(self_ty) = opt_self_ty else {
let guar = self.error_missing_qpath_self_ty(
let guar = self.report_missing_self_ty_for_resolved_path(
trait_def_id,
hir_ty.span,
item_segment,
Expand Down Expand Up @@ -713,120 +713,51 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
Err(guar) => Ty::new_error(tcx, guar),
}
}
hir::QPath::TypeRelative(qself, item_segment)
if item_segment.args.is_some_and(|args| {
hir::QPath::TypeRelative(hir_self_ty, segment)
if segment.args.is_some_and(|args| {
matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
}) =>
{
match self
.resolve_type_relative_return_type_notation(
qself,
item_segment,
hir_ty.hir_id,
hir_ty.span,
)
.and_then(|(candidate, item_def_id)| {
self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span)
}) {
Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
Err(guar) => Ty::new_error(tcx, guar),
}
}
_ => self.lower_ty(hir_ty),
}
}

/// Perform type-dependent lookup for a *method* for return type notation.
/// This generally mirrors `<dyn HirTyLowerer>::lower_assoc_path`.
fn resolve_type_relative_return_type_notation(
&self,
qself: &'tcx hir::Ty<'tcx>,
item_segment: &'tcx hir::PathSegment<'tcx>,
qpath_hir_id: HirId,
span: Span,
) -> Result<(ty::PolyTraitRef<'tcx>, DefId), ErrorGuaranteed> {
let tcx = self.tcx();
let qself_ty = self.lower_ty(qself);
let assoc_ident = item_segment.ident;
let qself_res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind {
path.res
} else {
Res::Err
};

let bound = match (qself_ty.kind(), qself_res) {
(_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => {
// `Self` in an impl of a trait -- we have a concrete self type and a
// trait reference.
let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else {
// A cycle error occurred, most likely.
self.dcx().span_bug(span, "expected cycle error");
};

self.probe_single_bound_for_assoc_item(
|| {
traits::supertraits(
tcx,
ty::Binder::dummy(trait_ref.instantiate_identity()),
)
},
AssocItemQSelf::SelfTyAlias,
let self_ty = self.lower_ty(hir_self_ty);
let (item_def_id, bound) = match self.resolve_type_relative_path(
self_ty,
hir_self_ty,
ty::AssocTag::Fn,
assoc_ident,
span,
segment,
hir_ty.hir_id,
hir_ty.span,
None,
)?
}
(
&ty::Param(_),
Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did),
) => self.probe_single_ty_param_bound_for_assoc_item(
param_did.expect_local(),
qself.span,
ty::AssocTag::Fn,
assoc_ident,
span,
)?,
_ => {
if let Err(reported) = qself_ty.error_reported() {
return Err(reported);
} else {
// FIXME(return_type_notation): Provide some structured suggestion here.
let err = struct_span_code_err!(
self.dcx(),
span,
E0223,
"ambiguous associated function"
) {
Ok(result) => result,
Err(guar) => return Ty::new_error(tcx, guar),
};

// Don't let `T::method` resolve to some `for<'a> <T as Tr<'a>>::method`,
// which may happen via a higher-ranked where clause or supertrait.
// This is the same restrictions as associated types; even though we could
// support it, it just makes things a lot more difficult to support in
// `resolve_bound_vars`, since we'd need to introduce those as elided
// bound vars on the where clause too.
if bound.has_bound_vars() {
return Ty::new_error(
tcx,
self.dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
span: hir_ty.span,
inferred_sugg: Some(hir_ty.span.with_hi(segment.ident.span.lo())),
bound: format!("{}::", tcx.anonymize_bound_vars(bound).skip_binder()),
mpart_sugg: None,
what: tcx.def_descr(item_def_id),
}),
);
return Err(err.emit());
}
}
};

// Don't let `T::method` resolve to some `for<'a> <T as Tr<'a>>::method`,
// which may happen via a higher-ranked where clause or supertrait.
// This is the same restrictions as associated types; even though we could
// support it, it just makes things a lot more difficult to support in
// `resolve_bound_vars`, since we'd need to introduce those as elided
// bound vars on the where clause too.
if bound.has_bound_vars() {
return Err(self.tcx().dcx().emit_err(
errors::AssociatedItemTraitUninferredGenericParams {
span,
inferred_sugg: Some(span.with_hi(item_segment.ident.span.lo())),
bound: format!("{}::", tcx.anonymize_bound_vars(bound).skip_binder(),),
mpart_sugg: None,
what: "function",
},
));
match self.lower_return_type_notation_ty(bound, item_def_id, hir_ty.span) {
Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
Err(guar) => Ty::new_error(tcx, guar),
}
}
_ => self.lower_ty(hir_ty),
}

let trait_def_id = bound.def_id();
let assoc_ty = self
.probe_assoc_item(assoc_ident, ty::AssocTag::Fn, qpath_hir_id, span, trait_def_id)
.expect("failed to find associated type");

Ok((bound, assoc_ty.def_id))
}

/// Do the common parts of lowering an RTN type. This involves extending the
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub(crate) fn validate_cmse_abi<'tcx>(
_ => tcx.hir_span(hir_id),
};
struct_span_code_err!(
tcx.dcx(),
dcx,
span,
E0781,
"the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {

// We don't support empty trait objects.
if regular_traits.is_empty() && auto_traits.is_empty() {
let guar = self.report_trait_object_with_no_traits_error(
span,
user_written_bounds.iter().copied(),
);
let guar =
self.report_trait_object_with_no_traits(span, user_written_bounds.iter().copied());
return Ty::new_error(tcx, guar);
}
// We don't support >1 principal
if regular_traits.len() > 1 {
let guar = self.report_trait_object_addition_traits_error(&regular_traits);
let guar = self.report_trait_object_addition_traits(&regular_traits);
return Ty::new_error(tcx, guar);
}
// Don't create a dyn trait if we have errors in the principal.
Expand Down Expand Up @@ -132,7 +130,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
if references_self {
// With trait alias and type alias combined, type resolver
// may not be able to catch all illegal `Self` usages (issue 139082)
let guar = tcx.dcx().emit_err(SelfInTypeAlias { span });
let guar = self.dcx().emit_err(SelfInTypeAlias { span });
b.term = replace_dummy_self_with_error(tcx, b.term, guar);
}
}
Expand Down Expand Up @@ -344,7 +342,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
hir_bound.trait_ref.path.res == Res::Def(DefKind::Trait, trait_ref.def_id)
&& hir_bound.span.contains(span)
});
self.complain_about_missing_type_params(
self.report_missing_type_params(
missing_type_params,
trait_ref.def_id,
span,
Expand Down
Loading
Loading