Skip to content

[WIP] [experimental] Move some impl trait validation #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
@@ -470,7 +470,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
ty: &Ty,
span: Span,
body: Option<&Expr>,
impl_trait_position: ImplTraitPosition,
impl_trait_position: ImplTraitPosition<'_>,
) -> (&'hir hir::Ty<'hir>, hir::BodyId) {
let ty = self.lower_ty(ty, ImplTraitContext::Disallowed(impl_trait_position));
(ty, self.lower_const_body(span, body))
@@ -1418,7 +1418,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
generics: &Generics,
constness: Const,
parent_node_id: NodeId,
itctx: ImplTraitContext,
itctx: ImplTraitContext<'_>,
f: impl FnOnce(&mut Self) -> T,
) -> (&'hir hir::Generics<'hir>, T) {
debug_assert!(self.impl_trait_defs.is_empty());
@@ -1624,7 +1624,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
bounds: &[GenericBound],
colon_span: Option<Span>,
parent_span: Span,
itctx: ImplTraitContext,
itctx: ImplTraitContext<'_>,
origin: PredicateOrigin,
) -> Option<hir::WherePredicate<'hir>> {
// Do not create a clause if we do not have anything inside it.
51 changes: 29 additions & 22 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
@@ -255,7 +255,7 @@ impl ResolverAstLowering {
/// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree,
/// and if so, what meaning it has.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum ImplTraitContext {
enum ImplTraitContext<'a> {
/// Treat `impl Trait` as shorthand for a new universal generic parameter.
/// Example: `fn foo(x: impl Debug)`, where `impl Debug` is conceptually
/// equivalent to a fresh universal parameter like `fn foo<T: Debug>(x: T)`.
@@ -274,14 +274,14 @@ enum ImplTraitContext {
fn_kind: Option<FnDeclKind>,
},
/// `impl Trait` is unstably accepted in this position.
FeatureGated(ImplTraitPosition, Symbol),
FeatureGated(ImplTraitPosition<'a>, Symbol),
/// `impl Trait` is not accepted in this position.
Disallowed(ImplTraitPosition),
Disallowed(ImplTraitPosition<'a>),
}

/// Position in which `impl Trait` is disallowed.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum ImplTraitPosition {
enum ImplTraitPosition<'a> {
Path,
Variable,
Trait,
@@ -303,9 +303,10 @@ enum ImplTraitPosition {
Cast,
ImplSelf,
OffsetOf,
ImplTrait { outer: &'a ImplTraitContext<'a> },
}

impl std::fmt::Display for ImplTraitPosition {
impl std::fmt::Display for ImplTraitPosition<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let name = match self {
ImplTraitPosition::Path => "paths",
@@ -329,6 +330,7 @@ impl std::fmt::Display for ImplTraitPosition {
ImplTraitPosition::Cast => "cast expression types",
ImplTraitPosition::ImplSelf => "impl headers",
ImplTraitPosition::OffsetOf => "`offset_of!` parameters",
ImplTraitPosition::ImplTrait { .. } => "`impl Trait`",
};

write!(f, "{name}")
@@ -979,7 +981,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_assoc_ty_constraint(
&mut self,
constraint: &AssocConstraint,
itctx: ImplTraitContext,
itctx: ImplTraitContext<'_>,
) -> hir::TypeBinding<'hir> {
debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx);
// lower generic arguments of identifier in constraint
@@ -1129,7 +1131,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_generic_arg(
&mut self,
arg: &ast::GenericArg,
itctx: ImplTraitContext,
itctx: ImplTraitContext<'_>,
) -> hir::GenericArg<'hir> {
match arg {
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(lt)),
@@ -1208,7 +1210,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}

#[instrument(level = "debug", skip(self))]
fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> &'hir hir::Ty<'hir> {
fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext<'_>) -> &'hir hir::Ty<'hir> {
self.arena.alloc(self.lower_ty_direct(t, itctx))
}

@@ -1218,7 +1220,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
qself: &Option<ptr::P<QSelf>>,
path: &Path,
param_mode: ParamMode,
itctx: ImplTraitContext,
itctx: ImplTraitContext<'_>,
) -> hir::Ty<'hir> {
// Check whether we should interpret this as a bare trait object.
// This check mirrors the one in late resolution. We only introduce this special case in
@@ -1260,7 +1262,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
self.ty(span, hir::TyKind::Tup(tys))
}

fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext) -> hir::Ty<'hir> {
fn lower_ty_direct(&mut self, t: &Ty, itctx: ImplTraitContext<'_>) -> hir::Ty<'hir> {
let kind = match &t.kind {
TyKind::Infer => hir::TyKind::Infer,
TyKind::Err(guar) => hir::TyKind::Err(*guar),
@@ -1407,7 +1409,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
*def_node_id,
bounds,
fn_kind,
itctx,
ImplTraitContext::Disallowed(ImplTraitPosition::ImplTrait {
outer: &itctx,
}),
),
ImplTraitContext::Universal => {
let span = t.span;
@@ -1516,7 +1520,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
opaque_ty_node_id: NodeId,
bounds: &GenericBounds,
fn_kind: Option<FnDeclKind>,
itctx: ImplTraitContext,
itctx: ImplTraitContext<'_>,
) -> hir::TyKind<'hir> {
// Make sure we know that some funky desugaring has been going on here.
// This is a first: there is code in other places like for loop
@@ -1924,7 +1928,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
output: &FnRetTy,
coro: CoroutineKind,
opaque_ty_span: Span,
itctx: ImplTraitContext,
itctx: ImplTraitContext<'_>,
) -> hir::GenericBound<'hir> {
// Compute the `T` in `Future<Output = T>` from the return type.
let output_ty = match output {
@@ -1972,7 +1976,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_param_bound(
&mut self,
tpb: &GenericBound,
itctx: ImplTraitContext,
itctx: ImplTraitContext<'_>,
) -> hir::GenericBound<'hir> {
match tpb {
GenericBound::Trait(p, modifiers) => hir::GenericBound::Trait(
@@ -2151,7 +2155,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&mut self,
modifiers: ast::TraitBoundModifiers,
p: &TraitRef,
itctx: ImplTraitContext,
itctx: ImplTraitContext<'_>,
) -> hir::TraitRef<'hir> {
let path = match self.lower_qpath(
p.ref_id,
@@ -2171,7 +2175,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_poly_trait_ref(
&mut self,
p: &PolyTraitRef,
itctx: ImplTraitContext,
itctx: ImplTraitContext<'_>,
modifiers: ast::TraitBoundModifiers,
) -> hir::PolyTraitRef<'hir> {
let bound_generic_params =
@@ -2180,24 +2184,25 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
hir::PolyTraitRef { bound_generic_params, trait_ref, span: self.lower_span(p.span) }
}

fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> {
fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext<'_>) -> hir::MutTy<'hir> {
hir::MutTy { ty: self.lower_ty(&mt.ty, itctx), mutbl: mt.mutbl }
}

#[instrument(level = "debug", skip(self), ret)]
fn lower_param_bounds(
&mut self,
bounds: &[GenericBound],
itctx: ImplTraitContext,
itctx: ImplTraitContext<'_>,
) -> hir::GenericBounds<'hir> {
self.arena.alloc_from_iter(self.lower_param_bounds_mut(bounds, itctx))
}

fn lower_param_bounds_mut<'s>(
fn lower_param_bounds_mut<'s, 'c>(
&'s mut self,
bounds: &'s [GenericBound],
itctx: ImplTraitContext,
) -> impl Iterator<Item = hir::GenericBound<'hir>> + Captures<'s> + Captures<'a> {
itctx: ImplTraitContext<'c>,
) -> impl Iterator<Item = hir::GenericBound<'hir>> + Captures<'s> + Captures<'c> + Captures<'a>
{
bounds.iter().map(move |bound| self.lower_param_bound(bound, itctx))
}

@@ -2232,7 +2237,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
bounds,
/* colon_span */ None,
span,
ImplTraitContext::Universal,
ImplTraitContext::Disallowed(ImplTraitPosition::ImplTrait {
outer: &ImplTraitContext::Universal,
}),
hir::PredicateOrigin::ImplTrait,
);

45 changes: 30 additions & 15 deletions compiler/rustc_ast_lowering/src/path.rs
Original file line number Diff line number Diff line change
@@ -27,12 +27,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
qself: &Option<ptr::P<QSelf>>,
p: &Path,
param_mode: ParamMode,
itctx: ImplTraitContext,
itctx: ImplTraitContext<'_>,
// modifiers of the impl/bound if this is a trait path
modifiers: Option<ast::TraitBoundModifiers>,
) -> hir::QPath<'hir> {
let qself_position = qself.as_ref().map(|q| q.position);
let qself = qself.as_ref().map(|q| self.lower_ty(&q.ty, itctx));
let qself = qself
.as_ref()
.map(|q| self.lower_ty(&q.ty, ImplTraitContext::Disallowed(ImplTraitPosition::Path)));

let partial_res =
self.resolver.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err));
@@ -71,14 +73,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
res,
segments: self.arena.alloc_from_iter(p.segments[..proj_start].iter().enumerate().map(
|(i, segment)| {
let param_mode = match (qself_position, param_mode) {
let (param_mode, itctx) = match (qself_position, param_mode) {
(Some(j), ParamMode::Optional) if i < j => {
// This segment is part of the trait path in a
// qualified path - one of `a`, `b` or `Trait`
// in `<X as a::b::Trait>::T::U::method`.
ParamMode::Explicit
// This segment is part of the trait path in a qualified path:
// One of `a`, `b` or `Trait` in `<X as a::b::Trait>::T::U::method`.
// `impl Trait` is unconditionally disallowed here.
(
ParamMode::Explicit,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
)
}
_ => param_mode,
_ => (param_mode, itctx),
};

let parenthesized_generic_args = match base_res {
@@ -162,6 +167,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
segment,
param_mode,
ParenthesizedGenericArgs::Err,
// Whether `impl Trait` is allowed here depends on the context contrary to
// the self type and trait segment paths in qualified paths (see above).
itctx,
None,
None,
@@ -220,7 +227,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
segment: &PathSegment,
param_mode: ParamMode,
parenthesized_generic_args: ParenthesizedGenericArgs,
itctx: ImplTraitContext,
itctx: ImplTraitContext<'_>,
constness: Option<ast::BoundConstness>,
// Additional features ungated with a bound modifier like `async`.
// This is passed down to the implicit associated type binding in
@@ -374,7 +381,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&mut self,
data: &AngleBracketedArgs,
param_mode: ParamMode,
itctx: ImplTraitContext,
itctx: ImplTraitContext<'_>,
) -> (GenericArgsCtor<'hir>, bool) {
let has_non_lt_args = data.args.iter().any(|arg| match arg {
AngleBracketedArg::Arg(ast::GenericArg::Lifetime(_))
@@ -389,10 +396,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
AngleBracketedArg::Constraint(_) => None,
})
.collect();
let bindings = self.arena.alloc_from_iter(data.args.iter().filter_map(|arg| match arg {
AngleBracketedArg::Constraint(c) => Some(self.lower_assoc_ty_constraint(c, itctx)),
AngleBracketedArg::Arg(_) => None,
}));
let bindings = {
// FIXME(fmease): explainer
let itctx = match itctx {
ImplTraitContext::Disallowed(ImplTraitPosition::ImplTrait { outer }) => *outer,
itctx => itctx,
};

self.arena.alloc_from_iter(data.args.iter().filter_map(|arg| match arg {
AngleBracketedArg::Constraint(c) => Some(self.lower_assoc_ty_constraint(c, itctx)),
AngleBracketedArg::Arg(_) => None,
}))
};
let ctor = GenericArgsCtor {
args,
bindings,
@@ -405,7 +420,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
fn lower_parenthesized_parameter_data(
&mut self,
data: &ParenthesizedArgs,
itctx: ImplTraitContext,
itctx: ImplTraitContext<'_>,
bound_modifier_allowed_features: Option<Lrc<[Symbol]>>,
) -> (GenericArgsCtor<'hir>, bool) {
// Switch to `PassThrough` mode for anonymous lifetimes; this
6 changes: 0 additions & 6 deletions compiler/rustc_ast_passes/messages.ftl
Original file line number Diff line number Diff line change
@@ -149,8 +149,6 @@ ast_passes_generic_before_constraints = generic arguments must come before the f

ast_passes_generic_default_trailing = generic parameters with a default must be trailing

ast_passes_impl_trait_path = `impl Trait` is not allowed in path parameters

ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
.help = remove one of these features

@@ -191,10 +189,6 @@ ast_passes_negative_bound_not_supported =
ast_passes_negative_bound_with_parenthetical_notation =
parenthetical notation may not be used for negative bounds

ast_passes_nested_impl_trait = nested `impl Trait` is not allowed
.outer = outer `impl Trait`
.inner = nested `impl Trait` here

ast_passes_nested_lifetimes = nested quantification of lifetimes

ast_passes_nomangle_ascii = `#[no_mangle]` requires ASCII identifier
Loading