Skip to content

Commit f4b7ea0

Browse files
author
addie.sh
committed
this is really messy I'm so sorry
1 parent 7e118ff commit f4b7ea0

10 files changed

Lines changed: 588 additions & 112 deletions

File tree

compiler/rustc_hir/src/hir.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,7 @@ pub enum GenericParamKind<'hir> {
830830
/// A lifetime definition (e.g., `'a: 'b + 'c + 'd`).
831831
Lifetime {
832832
kind: LifetimeParamKind,
833+
// FIXME(addiesh): add late_bound: bool,
833834
},
834835
Type {
835836
default: Option<&'hir Ty<'hir>>,

compiler/rustc_hir_analysis/src/collect/generics_of.rs

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,10 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
6060
parent: Some(trait_def_id),
6161
parent_count,
6262
own_params,
63+
own_all_params: opaque_ty_generics.own_all_params.clone(),
6364
param_def_id_to_index,
6465
has_self: opaque_ty_generics.has_self,
65-
has_late_bound_regions: opaque_ty_generics.has_late_bound_regions,
66+
own_late_bound_regions: opaque_ty_generics.own_late_bound_regions.clone(),
6667
};
6768
}
6869

@@ -154,9 +155,10 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
154155
parent: generics.parent,
155156
parent_count: generics.parent_count,
156157
own_params,
158+
own_all_params: generics.own_all_params.clone(),
157159
param_def_id_to_index,
158160
has_self: generics.has_self,
159-
has_late_bound_regions: generics.has_late_bound_regions,
161+
own_late_bound_regions: generics.own_late_bound_regions.clone(),
160162
};
161163
}
162164
ty::AnonConstKind::GCE => Some(parent_did),
@@ -268,6 +270,22 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
268270
own_params.push(opt_self);
269271
}
270272

273+
let all_lifetimes = hir_generics
274+
.params
275+
.iter()
276+
.enumerate()
277+
.filter_map(|(i, param)| match param.kind {
278+
GenericParamKind::Lifetime { .. } => Some(ty::GenericParamDef {
279+
name: param.name.ident().name,
280+
index: own_start + i as u32,
281+
def_id: param.def_id.to_def_id(),
282+
pure_wrt_drop: param.pure_wrt_drop,
283+
kind: ty::GenericParamDefKind::Lifetime,
284+
}),
285+
_ => None,
286+
})
287+
.collect::<Vec<_>>();
288+
271289
let early_lifetimes = super::early_bound_lifetimes_from_generics(tcx, hir_generics);
272290
own_params.extend(early_lifetimes.enumerate().map(|(i, param)| ty::GenericParamDef {
273291
name: param.name.ident().name,
@@ -393,9 +411,10 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
393411
parent: parent_def_id.map(LocalDefId::to_def_id),
394412
parent_count,
395413
own_params,
414+
own_all_params: all_lifetimes,
396415
param_def_id_to_index,
397416
has_self: has_self || parent_has_self,
398-
has_late_bound_regions: has_late_bound_regions(tcx, node),
417+
own_late_bound_regions: late_bound_regions(tcx, node),
399418
}
400419
}
401420

@@ -441,7 +460,7 @@ fn param_default_policy(node: Node<'_>) -> Option<ParamDefaultPolicy> {
441460
})
442461
}
443462

444-
fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<Span> {
463+
fn late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Vec<Span> {
445464
struct LateBoundRegionsDetector<'tcx> {
446465
tcx: TyCtxt<'tcx>,
447466
outer_index: ty::DebruijnIndex,
@@ -494,25 +513,37 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
494513
}
495514
}
496515

497-
fn has_late_bound_regions<'tcx>(
516+
fn late_bound_regions<'tcx>(
498517
tcx: TyCtxt<'tcx>,
499518
generics: &'tcx hir::Generics<'tcx>,
500519
decl: &'tcx hir::FnDecl<'tcx>,
501-
) -> Option<Span> {
520+
) -> Vec<Span> {
502521
let mut visitor = LateBoundRegionsDetector { tcx, outer_index: ty::INNERMOST };
503-
for param in generics.params {
504-
if let GenericParamKind::Lifetime { .. } = param.kind {
505-
if tcx.is_late_bound(param.hir_id) {
506-
return Some(param.span);
522+
523+
let spans = generics
524+
.params
525+
.iter()
526+
.flat_map(|param| {
527+
if let GenericParamKind::Lifetime { .. } = param.kind
528+
&& tcx.is_late_bound(param.hir_id)
529+
{
530+
Some(param.span)
531+
} else {
532+
None
507533
}
508-
}
534+
})
535+
.collect::<Vec<_>>();
536+
537+
if !spans.is_empty() {
538+
spans
539+
} else {
540+
visitor.visit_fn_decl(decl).break_value().map_or_default(|val| vec![val])
509541
}
510-
visitor.visit_fn_decl(decl).break_value()
511542
}
512543

513-
let decl = node.fn_decl()?;
514-
let generics = node.generics()?;
515-
has_late_bound_regions(tcx, generics, decl)
544+
let Some(decl) = node.fn_decl() else { return vec![] };
545+
let Some(generics) = node.generics() else { return vec![] };
546+
late_bound_regions(tcx, generics, decl)
516547
}
517548

518549
struct AnonConstInParamTyDetector {

compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs

Lines changed: 54 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,8 @@ pub(crate) fn check_generic_arg_count(
409409
has_self: bool,
410410
) -> GenericArgCountResult {
411411
let gen_args = seg.args();
412+
let tcx = cx.tcx();
413+
let kind = tcx.def_kind(def_id);
412414
let default_counts = gen_params.own_defaults();
413415
let param_counts = gen_params.own_counts();
414416

@@ -430,14 +432,28 @@ pub(crate) fn check_generic_arg_count(
430432
prohibit_assoc_item_constraint(cx, c, None);
431433
}
432434

433-
let tcx = cx.tcx();
435+
// this works!
436+
// let hidden_early_bound = 0;
437+
let hidden_early_bound = if matches!(gen_pos, GenericArgPosition::Value(_)) {
438+
gen_params.own_params.iter().filter(|x| x.is_anonymous_lifetime()).count()
439+
} else {
440+
0
441+
};
442+
443+
let hidden_lifetimes = if matches!(gen_pos, GenericArgPosition::Value(_)) {
444+
gen_params.own_all_params.iter().filter(|x| x.is_anonymous_lifetime()).count()
445+
} else {
446+
0
447+
};
448+
449+
let late_bound_lt_count = gen_params.own_late_bound_regions.len();
434450

435-
let kind = tcx.def_kind(def_id);
436451
if kind.is_fn_like() {
437452
tracing::info!("we are using fn-like {:?} ({gen_pos:?})", tcx.item_name(def_id));
438453
}
439-
tracing::info!(?gen_args);
440-
tracing::info!(?gen_params);
454+
tracing::info!(?late_bound_lt_count);
455+
tracing::info!("# gen_args = {}", gen_args.args.len());
456+
tracing::info!("ALL gen_params={:?}", gen_params.own_all_params);
441457

442458
// Suppress this warning for delegations as it is compiler generated and lifetimes are
443459
// propagated while late-bound lifetimes may be present.
@@ -448,56 +464,44 @@ pub(crate) fn check_generic_arg_count(
448464

449465
let mut invalid_args = vec![];
450466

451-
let mut check_lifetime_args = |min_expected_args: usize,
452-
max_expected_args: usize,
453-
provided_args: usize,
454-
late_bounds_ignore: bool| {
455-
if (min_expected_args..=max_expected_args).contains(&provided_args) {
456-
return Ok(());
457-
}
458-
459-
if late_bounds_ignore {
460-
return Ok(());
461-
}
467+
let mut check_lifetime_args =
468+
|min_expected_args: usize, max_expected_args: usize, provided_args: usize| {
469+
if (min_expected_args..=max_expected_args).contains(&provided_args) {
470+
return Ok(());
471+
}
462472

463-
invalid_args.extend(min_expected_args..provided_args);
473+
invalid_args.extend(min_expected_args..provided_args);
464474

465-
let gen_args_info = if provided_args > min_expected_args {
466-
let num_redundant_args = provided_args - min_expected_args;
467-
GenericArgsInfo::ExcessLifetimes { num_redundant_args }
468-
} else {
469-
let num_missing_args = min_expected_args - provided_args;
470-
GenericArgsInfo::MissingLifetimes { num_missing_args }
475+
let gen_args_info = if provided_args > min_expected_args {
476+
let num_redundant_args = provided_args - min_expected_args;
477+
GenericArgsInfo::ExcessLifetimes { num_redundant_args }
478+
} else {
479+
let num_missing_args = min_expected_args - provided_args;
480+
GenericArgsInfo::MissingLifetimes { num_missing_args }
481+
};
482+
483+
let reported = cx.dcx().emit_err(WrongNumberOfGenericArgs::new(
484+
tcx,
485+
gen_args_info,
486+
seg,
487+
gen_params,
488+
has_self as usize,
489+
gen_args,
490+
def_id,
491+
));
492+
493+
Err(reported)
471494
};
472495

473-
let reported = cx.dcx().emit_err(WrongNumberOfGenericArgs::new(
474-
tcx,
475-
gen_args_info,
476-
seg,
477-
gen_params,
478-
has_self as usize,
479-
gen_args,
480-
def_id,
481-
));
482-
483-
Err(reported)
484-
};
485-
486-
// this works!
487-
let hidden_early_bound = 0;
488-
// let hidden_early_bound = if matches!(gen_pos, GenericArgPosition::Value(_)) {
489-
// gen_params.own_params.iter().filter(|x| x.is_anonymous_lifetime()).count()
490-
// } else {
491-
// 0
492-
// };
493-
494496
let min_expected_lifetime_args =
495497
if infer_lifetimes { 0 } else { param_counts.lifetimes - hidden_early_bound };
496-
let max_expected_lifetime_args = param_counts.lifetimes - hidden_early_bound;
498+
let max_expected_lifetime_args =
499+
param_counts.lifetimes - hidden_lifetimes + late_bound_lt_count;
497500
let num_provided_lifetime_args = gen_args.num_lifetime_args();
498501

499502
tracing::info!(
500503
?hidden_early_bound,
504+
?hidden_lifetimes,
501505
?min_expected_lifetime_args,
502506
?max_expected_lifetime_args,
503507
?num_provided_lifetime_args,
@@ -507,7 +511,7 @@ pub(crate) fn check_generic_arg_count(
507511
min_expected_lifetime_args,
508512
max_expected_lifetime_args,
509513
num_provided_lifetime_args,
510-
explicit_late_bound == ExplicitLateBound::Yes,
514+
// explicit_late_bound == ExplicitLateBound::Yes,
511515
);
512516

513517
let mut check_types_and_consts = |expected_min,
@@ -668,11 +672,12 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes(
668672

669673
let param_counts = def.own_counts();
670674

671-
if let Some(span_late) = def.has_late_bound_regions
675+
// FIXME(addiesh): just turning off the diagnostic is probably not enough to solve the problem. see:
676+
// https://rust-lang.zulipchat.com/#narrow/channel/600108-t-types.2Fearly-late-cleanup/topic/turbofishing.20elided.20lifetimes/near/607748866
677+
if cx.tcx().features().late_bound_turbofishing() {
678+
ExplicitLateBound::Yes
679+
} else if let Some(span_late) = def.own_late_bound_regions.first().copied()
672680
&& args.has_lifetime_args()
673-
// FIXME(addiesh): just turning off the diagnostic is probably not enough to solve the problem. see:
674-
// https://rust-lang.zulipchat.com/#narrow/channel/600108-t-types.2Fearly-late-cleanup/topic/turbofishing.20elided.20lifetimes/near/607748866
675-
&& !cx.tcx().features().late_bound_turbofishing()
676681
{
677682
let gone_turbofishing = "this may change in the future; see issue #156581 <https://github.com/rust-lang/rust/issues/156581> for more information";
678683

compiler/rustc_middle/src/ty/generics.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,14 @@ pub struct Generics {
122122
pub parent: Option<DefId>,
123123
pub parent_count: usize,
124124
pub own_params: Vec<GenericParamDef>,
125+
pub own_all_params: Vec<GenericParamDef>,
125126

126127
/// Reverse map to the `index` field of each `GenericParamDef`.
127128
#[stable_hash(ignore)]
128129
pub param_def_id_to_index: FxHashMap<DefId, u32>,
129130

130131
pub has_self: bool,
131-
pub has_late_bound_regions: Option<Span>,
132+
pub own_late_bound_regions: Vec<Span>,
132133
}
133134

134135
impl std::fmt::Debug for Generics {
@@ -143,7 +144,7 @@ impl std::fmt::Debug for Generics {
143144
.field("own_params", &self.own_params)
144145
.field("param_def_id_to_index", &stabilized_hashmap)
145146
.field("has_self", &self.has_self)
146-
.field("has_late_bound_regions", &self.has_late_bound_regions)
147+
.field("own_late_bound_regions", &self.own_late_bound_regions)
147148
.finish()
148149
}
149150
}

compiler/rustc_public/src/unstable/convert/stable/ty.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,8 +681,10 @@ impl<'tcx> Stable<'tcx> for ty::Generics {
681681
params,
682682
param_def_id_to_index,
683683
has_self: self.has_self,
684+
// FIXME: this type def has not been updated in rustc public
684685
has_late_bound_regions: self
685-
.has_late_bound_regions
686+
.own_late_bound_regions
687+
.first()
686688
.as_ref()
687689
.map(|late_bound_regions| late_bound_regions.stable(tables, cx)),
688690
}

compiler/rustc_ty_utils/src/assoc.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,10 @@ fn associated_type_for_impl_trait_in_impl(
356356
parent: Some(impl_local_def_id.to_def_id()),
357357
parent_count,
358358
own_params,
359+
own_all_params: trait_assoc_generics.own_all_params.clone(),
359360
param_def_id_to_index,
360361
has_self: false,
361-
has_late_bound_regions: trait_assoc_generics.has_late_bound_regions,
362+
own_late_bound_regions: trait_assoc_generics.own_late_bound_regions.clone(),
362363
}
363364
});
364365

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#![feature(late_bound_turbofishing)]
2+
3+
fn foo_early<'a: 'a>(b: &'a u32) -> &'a u32 { b }
4+
fn foo_late<'a>(b: &'a u32) -> &'a u32 { b }
5+
fn foo_latest(_: &u32) {}
6+
7+
fn require_static<T: 'static>(_: T) { }
8+
9+
fn main() {
10+
let f = foo_early::<'static>;
11+
require_static(f);
12+
let f = foo_late::<'static>;
13+
require_static(f);
14+
let f = foo_latest::<'static>;
15+
//~^ ERROR: function takes 0 lifetime arguments but 1 lifetime argument was supplied [E0107]
16+
require_static(f);
17+
}

0 commit comments

Comments
 (0)