Skip to content

Commit 51b51bb

Browse files
Implement RTN in resolve_bound_vars and HIR ty lowering
1 parent 19881b5 commit 51b51bb

File tree

11 files changed

+411
-177
lines changed

11 files changed

+411
-177
lines changed

compiler/rustc_ast_lowering/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -487,11 +487,12 @@ enum ParamMode {
487487

488488
#[derive(Copy, Clone, Debug)]
489489
enum AllowReturnTypeNotation {
490+
/// Only in types, since RTN is denied later during HIR lowering.
490491
Yes,
492+
/// All other positions (path expr, method, use tree).
491493
No,
492494
}
493495

494-
#[derive(Copy, Clone, Debug)]
495496
enum GenericArgsMode {
496497
ParenSugar,
497498
ReturnTypeNotation,
@@ -1239,7 +1240,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
12391240
qself,
12401241
path,
12411242
param_mode,
1242-
// We deny these after the fact in HIR->middle type lowering.
12431243
AllowReturnTypeNotation::Yes,
12441244
itctx,
12451245
None,

compiler/rustc_ast_lowering/src/path.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,9 @@ use super::errors::{
1616
GenericTypeWithParentheses, UseAngleBrackets,
1717
};
1818
use super::{
19-
AllowReturnTypeNotation, GenericArgsCtor, GenericArgsMode, ImplTraitContext, LifetimeRes,
20-
LoweringContext, ParamMode, ResolverAstLoweringExt,
19+
AllowReturnTypeNotation, GenericArgsCtor, GenericArgsMode, ImplTraitContext, ImplTraitPosition,
20+
LifetimeRes, LoweringContext, ParamMode, ResolverAstLoweringExt,
2121
};
22-
use crate::ImplTraitPosition;
2322

2423
impl<'a, 'hir> LoweringContext<'a, 'hir> {
2524
#[instrument(level = "trace", skip(self))]

compiler/rustc_hir_analysis/src/collect/predicates_of.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
240240
for predicate in hir_generics.predicates {
241241
match predicate {
242242
hir::WherePredicate::BoundPredicate(bound_pred) => {
243-
let ty = icx.lower_ty(bound_pred.bounded_ty);
243+
let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
244+
244245
let bound_vars = tcx.late_bound_vars(bound_pred.hir_id);
245246
// Keep the type around in a dummy predicate, in case of no bounds.
246247
// That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
@@ -770,6 +771,10 @@ impl<'tcx> ItemCtxt<'tcx> {
770771
continue;
771772
};
772773

774+
// Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we
775+
// want to only consider predicates with `Self: ...`, but we don't want
776+
// `OnlySelfBounds(true)` since we want to collect the nested associated
777+
// type bound as well.
773778
let (only_self_bounds, assoc_name) = match filter {
774779
PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
775780
(OnlySelfBounds(false), None)
@@ -780,14 +785,10 @@ impl<'tcx> ItemCtxt<'tcx> {
780785
}
781786
};
782787

783-
// Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we
784-
// want to only consider predicates with `Self: ...`, but we don't want
785-
// `OnlySelfBounds(true)` since we want to collect the nested associated
786-
// type bound as well.
787788
let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) {
788789
ty
789790
} else if matches!(filter, PredicateFilter::All) {
790-
self.lower_ty(predicate.bounded_ty)
791+
self.lowerer().lower_ty_maybe_return_type_notation(predicate.bounded_ty)
791792
} else {
792793
continue;
793794
};

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+109
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
889889
(pair, r)
890890
})
891891
.unzip();
892+
892893
self.record_late_bound_vars(hir_id, binders);
894+
895+
// If this is an RTN type in the self type, then append those to the binder.
896+
self.try_append_return_type_notation_params(hir_id, bounded_ty);
897+
893898
// Even if there are no lifetimes defined here, we still wrap it in a binder
894899
// scope. If there happens to be a nested poly trait ref (an error), that
895900
// will be `Concatenating` anyways, so we don't have to worry about the depth
@@ -1839,6 +1844,110 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
18391844
let old_value = self.map.defs.swap_remove(&lifetime_ref.hir_id);
18401845
assert_eq!(old_value, Some(bad_def));
18411846
}
1847+
1848+
// TODO:
1849+
fn try_append_return_type_notation_params(
1850+
&mut self,
1851+
hir_id: HirId,
1852+
hir_ty: &'tcx hir::Ty<'tcx>,
1853+
) {
1854+
let hir::TyKind::Path(qpath) = hir_ty.kind else {
1855+
// TODO:
1856+
return;
1857+
};
1858+
1859+
let (mut bound_vars, item_def_id, item_segment) = match qpath {
1860+
// TODO:
1861+
hir::QPath::Resolved(_, path)
1862+
if let [.., item_segment] = &path.segments[..]
1863+
&& item_segment.args.is_some_and(|args| {
1864+
matches!(
1865+
args.parenthesized,
1866+
hir::GenericArgsParentheses::ReturnTypeNotation
1867+
)
1868+
}) =>
1869+
{
1870+
let Res::Def(DefKind::AssocFn, item_def_id) = path.res else {
1871+
bug!();
1872+
};
1873+
(vec![], item_def_id, item_segment)
1874+
}
1875+
1876+
// TODO:
1877+
hir::QPath::TypeRelative(qself, item_segment)
1878+
if item_segment.args.is_some_and(|args| {
1879+
matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
1880+
}) =>
1881+
{
1882+
let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = qself.kind else {
1883+
return;
1884+
};
1885+
1886+
match path.res {
1887+
Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { trait_: _ } => {
1888+
let Some(generics) = self.tcx.hir_owner_node(hir_id.owner).generics()
1889+
else {
1890+
return;
1891+
};
1892+
1893+
let one_bound = generics.predicates.iter().find_map(|predicate| {
1894+
let hir::WherePredicate::BoundPredicate(predicate) = predicate else {
1895+
return None;
1896+
};
1897+
let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) =
1898+
predicate.bounded_ty.kind
1899+
else {
1900+
return None;
1901+
};
1902+
if bounded_path.res != path.res {
1903+
return None;
1904+
}
1905+
predicate.bounds.iter().find_map(|bound| {
1906+
let hir::GenericBound::Trait(trait_, _) = bound else {
1907+
return None;
1908+
};
1909+
BoundVarContext::supertrait_hrtb_vars(
1910+
self.tcx,
1911+
trait_.trait_ref.trait_def_id()?,
1912+
item_segment.ident,
1913+
ty::AssocKind::Fn,
1914+
)
1915+
})
1916+
});
1917+
let Some((bound_vars, assoc_item)) = one_bound else {
1918+
return;
1919+
};
1920+
(bound_vars, assoc_item.def_id, item_segment)
1921+
}
1922+
Res::SelfTyAlias { is_trait_impl: true, .. } => todo!(),
1923+
_ => return,
1924+
}
1925+
}
1926+
1927+
_ => return,
1928+
};
1929+
1930+
// TODO:
1931+
bound_vars.extend(self.tcx.generics_of(item_def_id).own_params.iter().map(|param| {
1932+
match param.kind {
1933+
ty::GenericParamDefKind::Lifetime => ty::BoundVariableKind::Region(
1934+
ty::BoundRegionKind::BrNamed(param.def_id, param.name),
1935+
),
1936+
ty::GenericParamDefKind::Type { .. } => {
1937+
ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(param.def_id, param.name))
1938+
}
1939+
ty::GenericParamDefKind::Const { .. } => ty::BoundVariableKind::Const,
1940+
}
1941+
}));
1942+
bound_vars.extend(self.tcx.fn_sig(item_def_id).instantiate_identity().bound_vars());
1943+
1944+
// TODO:
1945+
let existing_bound_vars = self.map.late_bound_vars.get_mut(&hir_id).unwrap();
1946+
let existing_bound_vars_saved = existing_bound_vars.clone();
1947+
existing_bound_vars.extend(bound_vars);
1948+
// TODO: subtle
1949+
self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved);
1950+
}
18421951
}
18431952

18441953
/// Detects late-bound lifetimes and inserts them into

0 commit comments

Comments
 (0)