Rollup merge of #120719 - compiler-errors:no-dyn-atb, r=lcnr
Remove support for `associated_type_bound` nested in `dyn` types These necessarily desugar to `impl Trait`, which is inconsistent with the `associated_type_bound` feature after #120584. This PR keeps the `is_in_dyn_type` hack, which kind of makes me sad. Ideally, we'd be validating that no object types have associated type bounds somewhere else. Unfortunately, we can't do this later during astconv (i think?), nor can we do it earlier during ast validation (i think?) because of the feature gating of ATB being a *warning* rather than an *error*. Let me know if you have thoughts about this. r? lcnr
This commit is contained in:
commit
e11e4446da
24 changed files with 91 additions and 429 deletions
|
@ -8,6 +8,10 @@ ast_lowering_arbitrary_expression_in_pattern =
|
|||
|
||||
ast_lowering_argument = argument
|
||||
|
||||
ast_lowering_assoc_ty_binding_in_dyn =
|
||||
associated type bounds are not allowed in `dyn` types
|
||||
.suggestion = use `impl Trait` to introduce a type instead
|
||||
|
||||
ast_lowering_assoc_ty_parentheses =
|
||||
parenthesized generic arguments cannot be used in associated type constraints
|
||||
|
||||
|
@ -100,9 +104,6 @@ ast_lowering_match_arm_with_no_body =
|
|||
`match` arm with no body
|
||||
.suggestion = add a body after the pattern
|
||||
|
||||
ast_lowering_misplaced_assoc_ty_binding =
|
||||
associated type bounds are only allowed in where clauses and function signatures, not in {$position}
|
||||
|
||||
ast_lowering_misplaced_double_dot =
|
||||
`..` patterns are not allowed here
|
||||
.note = only allowed in tuple, tuple struct, and slice patterns
|
||||
|
|
|
@ -94,11 +94,12 @@ pub struct MisplacedImplTrait<'a> {
|
|||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_lowering_misplaced_assoc_ty_binding)]
|
||||
pub struct MisplacedAssocTyBinding<'a> {
|
||||
#[diag(ast_lowering_assoc_ty_binding_in_dyn)]
|
||||
pub struct MisplacedAssocTyBinding {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub position: DiagnosticArgFromDisplay<'a>,
|
||||
#[suggestion(code = " = impl", applicability = "maybe-incorrect", style = "verbose")]
|
||||
pub suggestion: Option<Span>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic, Clone, Copy)]
|
||||
|
|
|
@ -197,7 +197,6 @@ trait ResolverAstLoweringExt {
|
|||
fn get_label_res(&self, id: NodeId) -> Option<NodeId>;
|
||||
fn get_lifetime_res(&self, id: NodeId) -> Option<LifetimeRes>;
|
||||
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>;
|
||||
fn remap_extra_lifetime_params(&mut self, from: NodeId, to: NodeId);
|
||||
}
|
||||
|
||||
impl ResolverAstLoweringExt for ResolverAstLowering {
|
||||
|
@ -256,11 +255,6 @@ impl ResolverAstLoweringExt for ResolverAstLowering {
|
|||
fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)> {
|
||||
self.extra_lifetime_params_map.remove(&id).unwrap_or_default()
|
||||
}
|
||||
|
||||
fn remap_extra_lifetime_params(&mut self, from: NodeId, to: NodeId) {
|
||||
let lifetimes = self.extra_lifetime_params_map.remove(&from).unwrap_or_default();
|
||||
self.extra_lifetime_params_map.insert(to, lifetimes);
|
||||
}
|
||||
}
|
||||
|
||||
/// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
|
||||
|
@ -1084,88 +1078,38 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
hir::TypeBindingKind::Equality { term }
|
||||
}
|
||||
AssocConstraintKind::Bound { bounds } => {
|
||||
enum DesugarKind {
|
||||
ImplTrait,
|
||||
Error(ImplTraitPosition),
|
||||
Bound,
|
||||
}
|
||||
// Disallow ATB in dyn types
|
||||
if self.is_in_dyn_type {
|
||||
let suggestion = match itctx {
|
||||
ImplTraitContext::ReturnPositionOpaqueTy { .. }
|
||||
| ImplTraitContext::TypeAliasesOpaqueTy { .. }
|
||||
| ImplTraitContext::Universal => {
|
||||
let bound_end_span = constraint
|
||||
.gen_args
|
||||
.as_ref()
|
||||
.map_or(constraint.ident.span, |args| args.span());
|
||||
if bound_end_span.eq_ctxt(constraint.span) {
|
||||
Some(self.tcx.sess.source_map().next_point(bound_end_span))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
// Piggy-back on the `impl Trait` context to figure out the correct behavior.
|
||||
let desugar_kind = match itctx {
|
||||
// in an argument, RPIT, or TAIT, if we are within a dyn type:
|
||||
//
|
||||
// fn foo(x: dyn Iterator<Item: Debug>)
|
||||
//
|
||||
// then desugar to:
|
||||
//
|
||||
// fn foo(x: dyn Iterator<Item = impl Debug>)
|
||||
//
|
||||
// This is because dyn traits must have all of their associated types specified.
|
||||
ImplTraitContext::ReturnPositionOpaqueTy { .. }
|
||||
| ImplTraitContext::TypeAliasesOpaqueTy { .. }
|
||||
| ImplTraitContext::Universal
|
||||
if self.is_in_dyn_type =>
|
||||
{
|
||||
DesugarKind::ImplTrait
|
||||
}
|
||||
let guar = self.dcx().emit_err(errors::MisplacedAssocTyBinding {
|
||||
span: constraint.span,
|
||||
suggestion,
|
||||
});
|
||||
let err_ty =
|
||||
&*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar)));
|
||||
hir::TypeBindingKind::Equality { term: err_ty.into() }
|
||||
} else {
|
||||
// Desugar `AssocTy: Bounds` into a type binding where the
|
||||
// later desugars into a trait predicate.
|
||||
let bounds = self.lower_param_bounds(bounds, itctx);
|
||||
|
||||
ImplTraitContext::Disallowed(position) if self.is_in_dyn_type => {
|
||||
DesugarKind::Error(position)
|
||||
}
|
||||
|
||||
// We are in the parameter position, but not within a dyn type:
|
||||
//
|
||||
// fn foo(x: impl Iterator<Item: Debug>)
|
||||
//
|
||||
// so we leave it as is and this gets expanded in astconv to a bound like
|
||||
// `<T as Iterator>::Item: Debug` where `T` is the type parameter for the
|
||||
// `impl Iterator`.
|
||||
_ => DesugarKind::Bound,
|
||||
};
|
||||
|
||||
match desugar_kind {
|
||||
DesugarKind::ImplTrait => {
|
||||
// Desugar `AssocTy: Bounds` into `AssocTy = impl Bounds`. We do this by
|
||||
// constructing the HIR for `impl bounds...` and then lowering that.
|
||||
|
||||
let impl_trait_node_id = self.next_node_id();
|
||||
// Shift `impl Trait` lifetime captures from the associated type bound's
|
||||
// node id to the opaque node id, so that the opaque can actually use
|
||||
// these lifetime bounds.
|
||||
self.resolver
|
||||
.remap_extra_lifetime_params(constraint.id, impl_trait_node_id);
|
||||
|
||||
self.with_dyn_type_scope(false, |this| {
|
||||
let node_id = this.next_node_id();
|
||||
let ty = this.lower_ty(
|
||||
&Ty {
|
||||
id: node_id,
|
||||
kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()),
|
||||
span: this.lower_span(constraint.span),
|
||||
tokens: None,
|
||||
},
|
||||
itctx,
|
||||
);
|
||||
|
||||
hir::TypeBindingKind::Equality { term: ty.into() }
|
||||
})
|
||||
}
|
||||
DesugarKind::Bound => {
|
||||
// Desugar `AssocTy: Bounds` into a type binding where the
|
||||
// later desugars into a trait predicate.
|
||||
let bounds = self.lower_param_bounds(bounds, itctx);
|
||||
|
||||
hir::TypeBindingKind::Constraint { bounds }
|
||||
}
|
||||
DesugarKind::Error(position) => {
|
||||
let guar = self.dcx().emit_err(errors::MisplacedAssocTyBinding {
|
||||
span: constraint.span,
|
||||
position: DiagnosticArgFromDisplay(&position),
|
||||
});
|
||||
let err_ty =
|
||||
&*self.arena.alloc(self.ty(constraint.span, hir::TyKind::Err(guar)));
|
||||
hir::TypeBindingKind::Equality { term: err_ty.into() }
|
||||
}
|
||||
hir::TypeBindingKind::Constraint { bounds }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue