Skip to content

Commit 773e8a5

Browse files
RTN
1 parent fb9ca92 commit 773e8a5

File tree

3 files changed

+120
-51
lines changed
  • compiler

3 files changed

+120
-51
lines changed

compiler/rustc_ast_lowering/src/lib.rs

+12
Original file line numberDiff line numberDiff line change
@@ -987,8 +987,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
987987
GenericArgs::AngleBracketed(data) => {
988988
self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).0
989989
}
990+
GenericArgs::Parenthesized(data)
991+
if self.tcx.features().return_type_notation =>
992+
{
993+
// TODO: Check the parens + no return type
994+
GenericArgsCtor {
995+
args: Default::default(),
996+
bindings: &[],
997+
parenthesized: true,
998+
span: data.span,
999+
}
1000+
}
9901001
GenericArgs::Parenthesized(data) => {
9911002
self.emit_bad_parenthesized_trait_in_assoc_ty(data);
1003+
// TODO: Add a RTN feature error if the parens are shaped correctly
9921004
self.lower_angle_bracketed_parameter_data(
9931005
&data.as_angle_bracketed_args(),
9941006
ParamMode::Explicit,

compiler/rustc_hir_analysis/src/astconv/mod.rs

+103-50
Original file line numberDiff line numberDiff line change
@@ -854,16 +854,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
854854
)
855855
}
856856

857-
fn trait_defines_associated_type_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool {
858-
self.tcx()
859-
.associated_items(trait_def_id)
860-
.find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, trait_def_id)
861-
.is_some()
862-
}
863-
fn trait_defines_associated_const_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool {
857+
fn trait_defines_associated_item_named(
858+
&self,
859+
trait_def_id: DefId,
860+
assoc_kind: ty::AssocKind,
861+
assoc_name: Ident,
862+
) -> bool {
864863
self.tcx()
865864
.associated_items(trait_def_id)
866-
.find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Const, trait_def_id)
865+
.find_by_name_and_kind(self.tcx(), assoc_name, assoc_kind, trait_def_id)
867866
.is_some()
868867
}
869868

@@ -1087,24 +1086,42 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
10871086

10881087
let tcx = self.tcx();
10891088

1090-
let candidate =
1091-
if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
1092-
// Simple case: X is defined in the current trait.
1089+
// TODO: rtn comment goes here
1090+
let associated_return_type_bound =
1091+
binding.gen_args.parenthesized && self.tcx().features().associated_return_type_bounds;
1092+
1093+
let candidate = if return_type_notation {
1094+
if self.trait_defines_associated_item_named(
1095+
trait_ref.def_id(),
1096+
ty::AssocKind::Fn,
1097+
binding.item_name,
1098+
) {
10931099
trait_ref
10941100
} else {
1095-
// Otherwise, we have to walk through the supertraits to find
1096-
// those that do.
1097-
self.one_bound_for_assoc_type(
1098-
|| traits::supertraits(tcx, trait_ref),
1099-
trait_ref.print_only_trait_path(),
1100-
binding.item_name,
1101-
path_span,
1102-
match binding.kind {
1103-
ConvertedBindingKind::Equality(term) => Some(term),
1104-
_ => None,
1105-
},
1106-
)?
1107-
};
1101+
// TODO: error
1102+
todo!()
1103+
}
1104+
} else if self.trait_defines_associated_item_named(
1105+
trait_ref.def_id(),
1106+
ty::AssocKind::Type,
1107+
binding.item_name,
1108+
) {
1109+
// Simple case: X is defined in the current trait.
1110+
trait_ref
1111+
} else {
1112+
// Otherwise, we have to walk through the supertraits to find
1113+
// those that do.
1114+
self.one_bound_for_assoc_type(
1115+
|| traits::supertraits(tcx, trait_ref),
1116+
trait_ref.print_only_trait_path(),
1117+
binding.item_name,
1118+
path_span,
1119+
match binding.kind {
1120+
ConvertedBindingKind::Equality(term) => Some(term),
1121+
_ => None,
1122+
},
1123+
)?
1124+
};
11081125

11091126
let (assoc_ident, def_scope) =
11101127
tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id);
@@ -1116,9 +1133,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
11161133
.filter_by_name_unhygienic(assoc_ident.name)
11171134
.find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident)
11181135
};
1119-
let assoc_item = find_item_of_kind(ty::AssocKind::Type)
1120-
.or_else(|| find_item_of_kind(ty::AssocKind::Const))
1121-
.expect("missing associated type");
1136+
let assoc_item = if return_type_notation {
1137+
find_item_of_kind(ty::AssocKind::Fn)
1138+
} else {
1139+
find_item_of_kind(ty::AssocKind::Type)
1140+
.or_else(|| find_item_of_kind(ty::AssocKind::Const))
1141+
}
1142+
.expect("missing associated type");
11221143

11231144
if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) {
11241145
tcx.sess
@@ -1145,28 +1166,54 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
11451166
.or_insert(binding.span);
11461167
}
11471168

1148-
// Include substitutions for generic parameters of associated types
1149-
let projection_ty = candidate.map_bound(|trait_ref| {
1150-
let ident = Ident::new(assoc_item.name, binding.item_name.span);
1151-
let item_segment = hir::PathSegment {
1152-
ident,
1153-
hir_id: binding.hir_id,
1154-
res: Res::Err,
1155-
args: Some(binding.gen_args),
1156-
infer_args: false,
1169+
let projection_ty = if associated_return_type_bound {
1170+
let generics = self.tcx().generics_of(assoc_item.def_id);
1171+
if !generics.params.is_empty() {
1172+
todo!();
1173+
}
1174+
let output = self.tcx().fn_sig(assoc_item.def_id).skip_binder().output();
1175+
let fn_bound_vars = output.bound_vars();
1176+
1177+
let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
1178+
&& tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder
1179+
{
1180+
alias_ty
1181+
} else {
1182+
todo!("found return type of {output:?}");
11571183
};
11581184

1159-
let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item(
1160-
path_span,
1161-
assoc_item.def_id,
1162-
&item_segment,
1163-
trait_ref.substs,
1164-
);
1185+
let trait_bound_vars = candidate.bound_vars();
1186+
let shifted_output = tcx.shift_bound_var_indices(trait_bound_vars.len(), output);
1187+
let subst_output =
1188+
ty::EarlyBinder(shifted_output).subst(tcx, candidate.skip_binder().substs);
1189+
let bound_vars =
1190+
tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(fn_bound_vars));
1191+
1192+
ty::Binder::bind_with_vars(subst_output, bound_vars)
1193+
} else {
1194+
// Include substitutions for generic parameters of associated types
1195+
candidate.map_bound(|trait_ref| {
1196+
let ident = Ident::new(assoc_item.name, binding.item_name.span);
1197+
let item_segment = hir::PathSegment {
1198+
ident,
1199+
hir_id: binding.hir_id,
1200+
res: Res::Err,
1201+
args: Some(binding.gen_args),
1202+
infer_args: false,
1203+
};
11651204

1166-
debug!(?substs_trait_ref_and_assoc_item);
1205+
let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item(
1206+
path_span,
1207+
assoc_item.def_id,
1208+
&item_segment,
1209+
trait_ref.substs,
1210+
);
11671211

1168-
self.tcx().mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item)
1169-
});
1212+
debug!(?substs_trait_ref_and_assoc_item);
1213+
1214+
self.tcx().mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item)
1215+
})
1216+
};
11701217

11711218
if !speculative {
11721219
// Find any late-bound regions declared in `ty` that are not
@@ -1206,6 +1253,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
12061253
}
12071254

12081255
match binding.kind {
1256+
ConvertedBindingKind::Equality(..) if associated_return_type_bound => {
1257+
// TODO: error
1258+
todo!()
1259+
}
12091260
ConvertedBindingKind::Equality(mut term) => {
12101261
// "Desugar" a constraint like `T: Iterator<Item = u32>` this to
12111262
// the "projection predicate" for:
@@ -1267,7 +1318,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
12671318
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
12681319
// parameter to have a skipped binder.
12691320
let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder());
1270-
self.add_bounds(param_ty, ast_bounds.iter(), bounds, candidate.bound_vars());
1321+
self.add_bounds(param_ty, ast_bounds.iter(), bounds, projection_ty.bound_vars());
12711322
}
12721323
}
12731324
Ok(())
@@ -1808,10 +1859,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
18081859
where
18091860
I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
18101861
{
1811-
let mut matching_candidates = all_candidates()
1812-
.filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name));
1813-
let mut const_candidates = all_candidates()
1814-
.filter(|r| self.trait_defines_associated_const_named(r.def_id(), assoc_name));
1862+
let mut matching_candidates = all_candidates().filter(|r| {
1863+
self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Type, assoc_name)
1864+
});
1865+
let mut const_candidates = all_candidates().filter(|r| {
1866+
self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Const, assoc_name)
1867+
});
18151868

18161869
let (bound, next_cand) = match (matching_candidates.next(), const_candidates.next()) {
18171870
(Some(bound), _) => (bound, matching_candidates.next()),

compiler/rustc_parse/src/parser/path.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -550,7 +550,11 @@ impl<'a> Parser<'a> {
550550

551551
// Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
552552
if let AssocConstraintKind::Bound { .. } = kind {
553-
self.sess.gated_spans.gate(sym::associated_type_bounds, span);
553+
if gen_args.as_ref().map_or(false, |args| args.is_parenthesized()) {
554+
self.sess.gated_spans.gate(sym::return_type_notation, span);
555+
} else {
556+
self.sess.gated_spans.gate(sym::associated_type_bounds, span);
557+
}
554558
}
555559
let constraint =
556560
AssocConstraint { id: ast::DUMMY_NODE_ID, ident, gen_args, kind, span };

0 commit comments

Comments
 (0)