Skip to content

Commit 94c19c6

Browse files
authored
Rollup merge of #125819 - oli-obk:localize, r=fmease
Various `HirTyLowerer` cleanups Previously there was some ad-hoc specialization going on, because you could call `allows_infer`, which basically was deciding between whether the trait object was backed by `FnCtxt` or by `ItemCtxt`. I moved all the different logic into dedicated methods on `HirTyLowerer` and removed `allows_infer` best reviewed commit-by-commit
2 parents e174512 + c8a331a commit 94c19c6

File tree

8 files changed

+221
-210
lines changed

8 files changed

+221
-210
lines changed

compiler/rustc_hir_analysis/src/collect.rs

+105-12
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ use rustc_ast::Recovered;
1818
use rustc_data_structures::captures::Captures;
1919
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
2020
use rustc_data_structures::unord::UnordMap;
21-
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
22-
use rustc_hir as hir;
21+
use rustc_errors::{struct_span_code_err, Applicability, Diag, ErrorGuaranteed, StashKey, E0228};
2322
use rustc_hir::def::DefKind;
2423
use rustc_hir::def_id::{DefId, LocalDefId};
25-
use rustc_hir::intravisit::{self, Visitor};
24+
use rustc_hir::intravisit::{self, walk_generics, Visitor};
25+
use rustc_hir::{self as hir};
2626
use rustc_hir::{GenericParamKind, Node};
2727
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
2828
use rustc_infer::traits::ObligationCause;
@@ -44,7 +44,7 @@ use std::ops::Bound;
4444

4545
use crate::check::intrinsic::intrinsic_operation_unsafety;
4646
use crate::errors;
47-
use crate::hir_ty_lowering::HirTyLowerer;
47+
use crate::hir_ty_lowering::{HirTyLowerer, RegionInferReason};
4848
pub use type_of::test_opaque_hidden_types;
4949

5050
mod generics_of;
@@ -370,16 +370,26 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
370370
self.tcx
371371
}
372372

373-
fn item_def_id(&self) -> DefId {
374-
self.item_def_id.to_def_id()
373+
fn item_def_id(&self) -> LocalDefId {
374+
self.item_def_id
375375
}
376376

377-
fn allow_infer(&self) -> bool {
378-
false
379-
}
380-
381-
fn re_infer(&self, _: Option<&ty::GenericParamDef>, _: Span) -> Option<ty::Region<'tcx>> {
382-
None
377+
fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> {
378+
if let RegionInferReason::BorrowedObjectLifetimeDefault = reason {
379+
let e = struct_span_code_err!(
380+
self.tcx().dcx(),
381+
span,
382+
E0228,
383+
"the lifetime bound for this object type cannot be deduced \
384+
from context; please supply an explicit bound"
385+
)
386+
.emit();
387+
self.set_tainted_by_errors(e);
388+
ty::Region::new_error(self.tcx(), e)
389+
} else {
390+
// This indicates an illegal lifetime in a non-assoc-trait position
391+
ty::Region::new_error_with_message(self.tcx(), span, "unelided lifetime in signature")
392+
}
383393
}
384394

385395
fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
@@ -510,6 +520,89 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
510520
fn set_tainted_by_errors(&self, err: ErrorGuaranteed) {
511521
self.tainted_by_errors.set(Some(err));
512522
}
523+
524+
fn lower_fn_sig(
525+
&self,
526+
decl: &hir::FnDecl<'tcx>,
527+
generics: Option<&hir::Generics<'_>>,
528+
hir_id: rustc_hir::HirId,
529+
hir_ty: Option<&hir::Ty<'_>>,
530+
) -> (Vec<Ty<'tcx>>, Ty<'tcx>) {
531+
let tcx = self.tcx();
532+
// We proactively collect all the inferred type params to emit a single error per fn def.
533+
let mut visitor = HirPlaceholderCollector::default();
534+
let mut infer_replacements = vec![];
535+
536+
if let Some(generics) = generics {
537+
walk_generics(&mut visitor, generics);
538+
}
539+
540+
let input_tys = decl
541+
.inputs
542+
.iter()
543+
.enumerate()
544+
.map(|(i, a)| {
545+
if let hir::TyKind::Infer = a.kind {
546+
if let Some(suggested_ty) =
547+
self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
548+
{
549+
infer_replacements.push((a.span, suggested_ty.to_string()));
550+
return Ty::new_error_with_message(tcx, a.span, suggested_ty.to_string());
551+
}
552+
}
553+
554+
// Only visit the type looking for `_` if we didn't fix the type above
555+
visitor.visit_ty(a);
556+
self.lowerer().lower_arg_ty(a, None)
557+
})
558+
.collect();
559+
560+
let output_ty = match decl.output {
561+
hir::FnRetTy::Return(output) => {
562+
if let hir::TyKind::Infer = output.kind
563+
&& let Some(suggested_ty) =
564+
self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
565+
{
566+
infer_replacements.push((output.span, suggested_ty.to_string()));
567+
Ty::new_error_with_message(tcx, output.span, suggested_ty.to_string())
568+
} else {
569+
visitor.visit_ty(output);
570+
self.lower_ty(output)
571+
}
572+
}
573+
hir::FnRetTy::DefaultReturn(..) => tcx.types.unit,
574+
};
575+
576+
if !(visitor.0.is_empty() && infer_replacements.is_empty()) {
577+
// We check for the presence of
578+
// `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`.
579+
580+
let mut diag = crate::collect::placeholder_type_error_diag(
581+
tcx,
582+
generics,
583+
visitor.0,
584+
infer_replacements.iter().map(|(s, _)| *s).collect(),
585+
true,
586+
hir_ty,
587+
"function",
588+
);
589+
590+
if !infer_replacements.is_empty() {
591+
diag.multipart_suggestion(
592+
format!(
593+
"try replacing `_` with the type{} in the corresponding trait method signature",
594+
rustc_errors::pluralize!(infer_replacements.len()),
595+
),
596+
infer_replacements,
597+
Applicability::MachineApplicable,
598+
);
599+
}
600+
601+
self.set_tainted_by_errors(diag.emit());
602+
}
603+
604+
(input_tys, output_ty)
605+
}
513606
}
514607

515608
/// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present.

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::bounds::Bounds;
22
use crate::collect::ItemCtxt;
33
use crate::constrained_generic_params as cgp;
4-
use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter};
4+
use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter, RegionInferReason};
55
use hir::{HirId, Node};
66
use rustc_data_structures::fx::FxIndexSet;
77
use rustc_hir as hir;
@@ -117,7 +117,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
117117
let mut is_trait = None;
118118
let mut is_default_impl_trait = None;
119119

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

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

246245
hir::WherePredicate::RegionPredicate(region_pred) => {
247-
let r1 = icx.lowerer().lower_lifetime(region_pred.lifetime, None);
246+
let r1 = icx
247+
.lowerer()
248+
.lower_lifetime(region_pred.lifetime, RegionInferReason::RegionPredicate);
248249
predicates.extend(region_pred.bounds.iter().map(|bound| {
249250
let (r2, span) = match bound {
250-
hir::GenericBound::Outlives(lt) => {
251-
(icx.lowerer().lower_lifetime(lt, None), lt.ident.span)
252-
}
251+
hir::GenericBound::Outlives(lt) => (
252+
icx.lowerer().lower_lifetime(lt, RegionInferReason::RegionPredicate),
253+
lt.ident.span,
254+
),
253255
bound => {
254256
span_bug!(
255257
bound.span(),

compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ use crate::bounds::Bounds;
1818
use crate::errors;
1919
use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter};
2020

21+
use super::RegionInferReason;
22+
2123
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
2224
/// Add a `Sized` bound to the `bounds` if appropriate.
2325
///
@@ -166,7 +168,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
166168
);
167169
}
168170
hir::GenericBound::Outlives(lifetime) => {
169-
let region = self.lower_lifetime(lifetime, None);
171+
let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
170172
bounds.push_region_bound(
171173
self.tcx(),
172174
ty::Binder::bind_with_vars(

0 commit comments

Comments
 (0)