Skip to content
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

Various HirTyLowerer cleanups #125819

Merged
merged 7 commits into from
Jun 5, 2024
117 changes: 105 additions & 12 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ use rustc_ast::Recovered;
use rustc_data_structures::captures::Captures;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_data_structures::unord::UnordMap;
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
use rustc_hir as hir;
use rustc_errors::{struct_span_code_err, Applicability, Diag, ErrorGuaranteed, StashKey, E0228};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::intravisit::{self, walk_generics, Visitor};
use rustc_hir::{self as hir};
use rustc_hir::{GenericParamKind, Node};
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
use rustc_infer::traits::ObligationCause;
Expand All @@ -44,7 +44,7 @@ use std::ops::Bound;

use crate::check::intrinsic::intrinsic_operation_unsafety;
use crate::errors;
use crate::hir_ty_lowering::HirTyLowerer;
use crate::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
pub use type_of::test_opaque_hidden_types;

mod generics_of;
Expand Down Expand Up @@ -370,16 +370,26 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
self.tcx
}

fn item_def_id(&self) -> DefId {
self.item_def_id.to_def_id()
fn item_def_id(&self) -> LocalDefId {
self.item_def_id
}

fn allow_infer(&self) -> bool {
false
}

fn re_infer(&self, _: Option<&ty::GenericParamDef>, _: Span) -> Option<ty::Region<'tcx>> {
None
fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> {
if let RegionInferReason::BorrowedObjectLifetimeDefault = reason {
let e = struct_span_code_err!(
self.tcx().dcx(),
span,
E0228,
"the lifetime bound for this object type cannot be deduced \
from context; please supply an explicit bound"
)
.emit();
self.set_tainted_by_errors(e);
ty::Region::new_error(self.tcx(), e)
} else {
// This indicates an illegal lifetime in a non-assoc-trait position
ty::Region::new_error_with_message(self.tcx(), span, "unelided lifetime in signature")
}
}

fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
Expand Down Expand Up @@ -510,6 +520,89 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
fn set_tainted_by_errors(&self, err: ErrorGuaranteed) {
self.tainted_by_errors.set(Some(err));
}

fn lower_fn_sig(
&self,
decl: &hir::FnDecl<'tcx>,
generics: Option<&hir::Generics<'_>>,
hir_id: rustc_hir::HirId,
hir_ty: Option<&hir::Ty<'_>>,
) -> (Vec<Ty<'tcx>>, Ty<'tcx>) {
let tcx = self.tcx();
// We proactively collect all the inferred type params to emit a single error per fn def.
let mut visitor = HirPlaceholderCollector::default();
let mut infer_replacements = vec![];

if let Some(generics) = generics {
walk_generics(&mut visitor, generics);
}

let input_tys = decl
.inputs
.iter()
.enumerate()
.map(|(i, a)| {
if let hir::TyKind::Infer = a.kind {
if let Some(suggested_ty) =
self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
{
infer_replacements.push((a.span, suggested_ty.to_string()));
return Ty::new_error_with_message(tcx, a.span, suggested_ty.to_string());
}
}

// Only visit the type looking for `_` if we didn't fix the type above
visitor.visit_ty(a);
self.lowerer().lower_arg_ty(a, None)
})
.collect();

let output_ty = match decl.output {
hir::FnRetTy::Return(output) => {
if let hir::TyKind::Infer = output.kind
&& let Some(suggested_ty) =
self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
{
infer_replacements.push((output.span, suggested_ty.to_string()));
Ty::new_error_with_message(tcx, output.span, suggested_ty.to_string())
} else {
visitor.visit_ty(output);
self.lower_ty(output)
}
}
hir::FnRetTy::DefaultReturn(..) => tcx.types.unit,
};

if !(visitor.0.is_empty() && infer_replacements.is_empty()) {
// We check for the presence of
// `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`.

let mut diag = crate::collect::placeholder_type_error_diag(
tcx,
generics,
visitor.0,
infer_replacements.iter().map(|(s, _)| *s).collect(),
true,
hir_ty,
"function",
);

if !infer_replacements.is_empty() {
diag.multipart_suggestion(
format!(
"try replacing `_` with the type{} in the corresponding trait method signature",
rustc_errors::pluralize!(infer_replacements.len()),
),
infer_replacements,
Applicability::MachineApplicable,
);
}

self.set_tainted_by_errors(diag.emit());
}

(input_tys, output_ty)
}
}

/// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present.
Expand Down
14 changes: 8 additions & 6 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::bounds::Bounds;
use crate::collect::ItemCtxt;
use crate::constrained_generic_params as cgp;
use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter};
use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter, RegionInferReason};
use hir::{HirId, Node};
use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
Expand Down Expand Up @@ -117,7 +117,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
let mut is_trait = None;
let mut is_default_impl_trait = None;

// FIXME: Should ItemCtxt take a LocalDefId?
let icx = ItemCtxt::new(tcx, def_id);

const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty();
Expand Down Expand Up @@ -244,12 +243,15 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
}

hir::WherePredicate::RegionPredicate(region_pred) => {
let r1 = icx.lowerer().lower_lifetime(region_pred.lifetime, None);
let r1 = icx
.lowerer()
.lower_lifetime(region_pred.lifetime, RegionInferReason::RegionPredicate);
predicates.extend(region_pred.bounds.iter().map(|bound| {
let (r2, span) = match bound {
hir::GenericBound::Outlives(lt) => {
(icx.lowerer().lower_lifetime(lt, None), lt.ident.span)
}
hir::GenericBound::Outlives(lt) => (
icx.lowerer().lower_lifetime(lt, RegionInferReason::RegionPredicate),
lt.ident.span,
),
bound => {
span_bug!(
bound.span(),
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ use crate::bounds::Bounds;
use crate::errors;
use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter};

use super::RegionInferReason;

impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// Add a `Sized` bound to the `bounds` if appropriate.
///
Expand Down Expand Up @@ -166,7 +168,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
);
}
hir::GenericBound::Outlives(lifetime) => {
let region = self.lower_lifetime(lifetime, None);
let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
bounds.push_region_bound(
self.tcx(),
ty::Binder::bind_with_vars(
Expand Down
Loading
Loading