Skip to content
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

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

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
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
Expand Up @@ -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))
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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.
Expand Down
51 changes: 29 additions & 22 deletions compiler/rustc_ast_lowering/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)`.
Expand All @@ -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,
Expand All @@ -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",
Expand All @@ -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}")
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)),
Expand Down Expand Up @@ -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))
}

Expand All @@ -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
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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,
Expand All @@ -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 =
Expand All @@ -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))
}

Expand Down Expand Up @@ -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,
);

Expand Down
45 changes: 30 additions & 15 deletions compiler/rustc_ast_lowering/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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(_))
Expand All @@ -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,
Expand All @@ -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
Expand Down
6 changes: 0 additions & 6 deletions compiler/rustc_ast_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down
Loading