RTN
This commit is contained in:
parent
fb9ca9223d
commit
773e8a5ad1
@ -987,8 +987,20 @@ fn lower_assoc_ty_constraint(
|
|||||||
GenericArgs::AngleBracketed(data) => {
|
GenericArgs::AngleBracketed(data) => {
|
||||||
self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).0
|
self.lower_angle_bracketed_parameter_data(data, ParamMode::Explicit, itctx).0
|
||||||
}
|
}
|
||||||
|
GenericArgs::Parenthesized(data)
|
||||||
|
if self.tcx.features().return_type_notation =>
|
||||||
|
{
|
||||||
|
// TODO: Check the parens + no return type
|
||||||
|
GenericArgsCtor {
|
||||||
|
args: Default::default(),
|
||||||
|
bindings: &[],
|
||||||
|
parenthesized: true,
|
||||||
|
span: data.span,
|
||||||
|
}
|
||||||
|
}
|
||||||
GenericArgs::Parenthesized(data) => {
|
GenericArgs::Parenthesized(data) => {
|
||||||
self.emit_bad_parenthesized_trait_in_assoc_ty(data);
|
self.emit_bad_parenthesized_trait_in_assoc_ty(data);
|
||||||
|
// TODO: Add a RTN feature error if the parens are shaped correctly
|
||||||
self.lower_angle_bracketed_parameter_data(
|
self.lower_angle_bracketed_parameter_data(
|
||||||
&data.as_angle_bracketed_args(),
|
&data.as_angle_bracketed_args(),
|
||||||
ParamMode::Explicit,
|
ParamMode::Explicit,
|
||||||
|
@ -854,16 +854,15 @@ fn create_substs_for_ast_trait_ref<'a>(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trait_defines_associated_type_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool {
|
fn trait_defines_associated_item_named(
|
||||||
|
&self,
|
||||||
|
trait_def_id: DefId,
|
||||||
|
assoc_kind: ty::AssocKind,
|
||||||
|
assoc_name: Ident,
|
||||||
|
) -> bool {
|
||||||
self.tcx()
|
self.tcx()
|
||||||
.associated_items(trait_def_id)
|
.associated_items(trait_def_id)
|
||||||
.find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, trait_def_id)
|
.find_by_name_and_kind(self.tcx(), assoc_name, assoc_kind, trait_def_id)
|
||||||
.is_some()
|
|
||||||
}
|
|
||||||
fn trait_defines_associated_const_named(&self, trait_def_id: DefId, assoc_name: Ident) -> bool {
|
|
||||||
self.tcx()
|
|
||||||
.associated_items(trait_def_id)
|
|
||||||
.find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Const, trait_def_id)
|
|
||||||
.is_some()
|
.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1087,24 +1086,42 @@ fn add_predicates_for_ast_type_binding(
|
|||||||
|
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
|
|
||||||
let candidate =
|
// TODO: rtn comment goes here
|
||||||
if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
|
let associated_return_type_bound =
|
||||||
// Simple case: X is defined in the current trait.
|
binding.gen_args.parenthesized && self.tcx().features().associated_return_type_bounds;
|
||||||
|
|
||||||
|
let candidate = if return_type_notation {
|
||||||
|
if self.trait_defines_associated_item_named(
|
||||||
|
trait_ref.def_id(),
|
||||||
|
ty::AssocKind::Fn,
|
||||||
|
binding.item_name,
|
||||||
|
) {
|
||||||
trait_ref
|
trait_ref
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, we have to walk through the supertraits to find
|
// TODO: error
|
||||||
// those that do.
|
todo!()
|
||||||
self.one_bound_for_assoc_type(
|
}
|
||||||
|| traits::supertraits(tcx, trait_ref),
|
} else if self.trait_defines_associated_item_named(
|
||||||
trait_ref.print_only_trait_path(),
|
trait_ref.def_id(),
|
||||||
binding.item_name,
|
ty::AssocKind::Type,
|
||||||
path_span,
|
binding.item_name,
|
||||||
match binding.kind {
|
) {
|
||||||
ConvertedBindingKind::Equality(term) => Some(term),
|
// Simple case: X is defined in the current trait.
|
||||||
_ => None,
|
trait_ref
|
||||||
},
|
} else {
|
||||||
)?
|
// Otherwise, we have to walk through the supertraits to find
|
||||||
};
|
// those that do.
|
||||||
|
self.one_bound_for_assoc_type(
|
||||||
|
|| traits::supertraits(tcx, trait_ref),
|
||||||
|
trait_ref.print_only_trait_path(),
|
||||||
|
binding.item_name,
|
||||||
|
path_span,
|
||||||
|
match binding.kind {
|
||||||
|
ConvertedBindingKind::Equality(term) => Some(term),
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
|
)?
|
||||||
|
};
|
||||||
|
|
||||||
let (assoc_ident, def_scope) =
|
let (assoc_ident, def_scope) =
|
||||||
tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id);
|
tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id);
|
||||||
@ -1116,9 +1133,13 @@ fn add_predicates_for_ast_type_binding(
|
|||||||
.filter_by_name_unhygienic(assoc_ident.name)
|
.filter_by_name_unhygienic(assoc_ident.name)
|
||||||
.find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident)
|
.find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident)
|
||||||
};
|
};
|
||||||
let assoc_item = find_item_of_kind(ty::AssocKind::Type)
|
let assoc_item = if return_type_notation {
|
||||||
.or_else(|| find_item_of_kind(ty::AssocKind::Const))
|
find_item_of_kind(ty::AssocKind::Fn)
|
||||||
.expect("missing associated type");
|
} else {
|
||||||
|
find_item_of_kind(ty::AssocKind::Type)
|
||||||
|
.or_else(|| find_item_of_kind(ty::AssocKind::Const))
|
||||||
|
}
|
||||||
|
.expect("missing associated type");
|
||||||
|
|
||||||
if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) {
|
if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) {
|
||||||
tcx.sess
|
tcx.sess
|
||||||
@ -1145,28 +1166,54 @@ fn add_predicates_for_ast_type_binding(
|
|||||||
.or_insert(binding.span);
|
.or_insert(binding.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include substitutions for generic parameters of associated types
|
let projection_ty = if associated_return_type_bound {
|
||||||
let projection_ty = candidate.map_bound(|trait_ref| {
|
let generics = self.tcx().generics_of(assoc_item.def_id);
|
||||||
let ident = Ident::new(assoc_item.name, binding.item_name.span);
|
if !generics.params.is_empty() {
|
||||||
let item_segment = hir::PathSegment {
|
todo!();
|
||||||
ident,
|
}
|
||||||
hir_id: binding.hir_id,
|
let output = self.tcx().fn_sig(assoc_item.def_id).skip_binder().output();
|
||||||
res: Res::Err,
|
let fn_bound_vars = output.bound_vars();
|
||||||
args: Some(binding.gen_args),
|
|
||||||
infer_args: false,
|
let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
|
||||||
|
&& tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder
|
||||||
|
{
|
||||||
|
alias_ty
|
||||||
|
} else {
|
||||||
|
todo!("found return type of {output:?}");
|
||||||
};
|
};
|
||||||
|
|
||||||
let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item(
|
let trait_bound_vars = candidate.bound_vars();
|
||||||
path_span,
|
let shifted_output = tcx.shift_bound_var_indices(trait_bound_vars.len(), output);
|
||||||
assoc_item.def_id,
|
let subst_output =
|
||||||
&item_segment,
|
ty::EarlyBinder(shifted_output).subst(tcx, candidate.skip_binder().substs);
|
||||||
trait_ref.substs,
|
let bound_vars =
|
||||||
);
|
tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(fn_bound_vars));
|
||||||
|
|
||||||
debug!(?substs_trait_ref_and_assoc_item);
|
ty::Binder::bind_with_vars(subst_output, bound_vars)
|
||||||
|
} else {
|
||||||
|
// Include substitutions for generic parameters of associated types
|
||||||
|
candidate.map_bound(|trait_ref| {
|
||||||
|
let ident = Ident::new(assoc_item.name, binding.item_name.span);
|
||||||
|
let item_segment = hir::PathSegment {
|
||||||
|
ident,
|
||||||
|
hir_id: binding.hir_id,
|
||||||
|
res: Res::Err,
|
||||||
|
args: Some(binding.gen_args),
|
||||||
|
infer_args: false,
|
||||||
|
};
|
||||||
|
|
||||||
self.tcx().mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item)
|
let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item(
|
||||||
});
|
path_span,
|
||||||
|
assoc_item.def_id,
|
||||||
|
&item_segment,
|
||||||
|
trait_ref.substs,
|
||||||
|
);
|
||||||
|
|
||||||
|
debug!(?substs_trait_ref_and_assoc_item);
|
||||||
|
|
||||||
|
self.tcx().mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item)
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
if !speculative {
|
if !speculative {
|
||||||
// Find any late-bound regions declared in `ty` that are not
|
// Find any late-bound regions declared in `ty` that are not
|
||||||
@ -1206,6 +1253,10 @@ fn add_predicates_for_ast_type_binding(
|
|||||||
}
|
}
|
||||||
|
|
||||||
match binding.kind {
|
match binding.kind {
|
||||||
|
ConvertedBindingKind::Equality(..) if associated_return_type_bound => {
|
||||||
|
// TODO: error
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
ConvertedBindingKind::Equality(mut term) => {
|
ConvertedBindingKind::Equality(mut term) => {
|
||||||
// "Desugar" a constraint like `T: Iterator<Item = u32>` this to
|
// "Desugar" a constraint like `T: Iterator<Item = u32>` this to
|
||||||
// the "projection predicate" for:
|
// the "projection predicate" for:
|
||||||
@ -1267,7 +1318,7 @@ fn add_predicates_for_ast_type_binding(
|
|||||||
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
|
// Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty`
|
||||||
// parameter to have a skipped binder.
|
// parameter to have a skipped binder.
|
||||||
let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder());
|
let param_ty = tcx.mk_alias(ty::Projection, projection_ty.skip_binder());
|
||||||
self.add_bounds(param_ty, ast_bounds.iter(), bounds, candidate.bound_vars());
|
self.add_bounds(param_ty, ast_bounds.iter(), bounds, projection_ty.bound_vars());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -1808,10 +1859,12 @@ fn one_bound_for_assoc_type<I>(
|
|||||||
where
|
where
|
||||||
I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
|
I: Iterator<Item = ty::PolyTraitRef<'tcx>>,
|
||||||
{
|
{
|
||||||
let mut matching_candidates = all_candidates()
|
let mut matching_candidates = all_candidates().filter(|r| {
|
||||||
.filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name));
|
self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Type, assoc_name)
|
||||||
let mut const_candidates = all_candidates()
|
});
|
||||||
.filter(|r| self.trait_defines_associated_const_named(r.def_id(), assoc_name));
|
let mut const_candidates = all_candidates().filter(|r| {
|
||||||
|
self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Const, assoc_name)
|
||||||
|
});
|
||||||
|
|
||||||
let (bound, next_cand) = match (matching_candidates.next(), const_candidates.next()) {
|
let (bound, next_cand) = match (matching_candidates.next(), const_candidates.next()) {
|
||||||
(Some(bound), _) => (bound, matching_candidates.next()),
|
(Some(bound), _) => (bound, matching_candidates.next()),
|
||||||
|
@ -550,7 +550,11 @@ fn parse_angle_arg(
|
|||||||
|
|
||||||
// Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
|
// Gate associated type bounds, e.g., `Iterator<Item: Ord>`.
|
||||||
if let AssocConstraintKind::Bound { .. } = kind {
|
if let AssocConstraintKind::Bound { .. } = kind {
|
||||||
self.sess.gated_spans.gate(sym::associated_type_bounds, span);
|
if gen_args.as_ref().map_or(false, |args| args.is_parenthesized()) {
|
||||||
|
self.sess.gated_spans.gate(sym::return_type_notation, span);
|
||||||
|
} else {
|
||||||
|
self.sess.gated_spans.gate(sym::associated_type_bounds, span);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let constraint =
|
let constraint =
|
||||||
AssocConstraint { id: ast::DUMMY_NODE_ID, ident, gen_args, kind, span };
|
AssocConstraint { id: ast::DUMMY_NODE_ID, ident, gen_args, kind, span };
|
||||||
|
Loading…
Reference in New Issue
Block a user