diff options
Diffstat (limited to 'compiler/rustc_ast_passes')
-rw-r--r-- | compiler/rustc_ast_passes/Cargo.toml | 2 | ||||
-rw-r--r-- | compiler/rustc_ast_passes/messages.ftl | 10 | ||||
-rw-r--r-- | compiler/rustc_ast_passes/src/ast_validation.rs | 219 | ||||
-rw-r--r-- | compiler/rustc_ast_passes/src/errors.rs | 30 | ||||
-rw-r--r-- | compiler/rustc_ast_passes/src/feature_gate.rs | 38 | ||||
-rw-r--r-- | compiler/rustc_ast_passes/src/lib.rs | 11 | ||||
-rw-r--r-- | compiler/rustc_ast_passes/src/show_span.rs | 12 |
7 files changed, 188 insertions, 134 deletions
diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml index 0001394c8..99e79f65f 100644 --- a/compiler/rustc_ast_passes/Cargo.toml +++ b/compiler/rustc_ast_passes/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start -itertools = "0.10.1" +itertools = "0.11" rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } rustc_attr = { path = "../rustc_attr" } diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index d22bae816..790b58313 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -174,6 +174,10 @@ ast_passes_item_underscore = `{$kind}` items in this context need a name ast_passes_keyword_lifetime = lifetimes cannot use keyword names +ast_passes_match_arm_with_no_body = + `match` arm with no body + .suggestion = add a body after the pattern + ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name .help = consider using the `#[path]` attribute to specify filesystem path @@ -218,9 +222,13 @@ ast_passes_static_without_body = .suggestion = provide a definition for the static ast_passes_tilde_const_disallowed = `~const` is not allowed here - .trait = trait objects cannot have `~const` trait bounds .closure = closures cannot have `~const` trait bounds .function = this function is not `const`, so it cannot have `~const` trait bounds + .trait = this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds + .trait_impl = this impl is not `const`, so it cannot have `~const` trait bounds + .impl = inherent impls cannot have `~const` trait bounds + .object = trait objects cannot have `~const` trait bounds + .item = this item cannot have `~const` trait bounds ast_passes_trait_fn_const = functions in traits cannot be declared const diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 3d0513c89..887cb434a 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -8,9 +8,9 @@ use itertools::{Either, Itertools}; use rustc_ast::ptr::P; -use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; +use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; +use rustc_ast::walk_list; use rustc_ast::*; -use rustc_ast::{walk_list, StaticItem}; use rustc_ast_pretty::pprust::{self, State}; use rustc_data_structures::fx::FxIndexMap; use rustc_feature::Features; @@ -40,6 +40,10 @@ enum SelfSemantic { enum DisallowTildeConstContext<'a> { TraitObject, Fn(FnKind<'a>), + Trait(Span), + TraitImpl(Span), + Impl(Span), + Item, } struct AstValidator<'a> { @@ -110,18 +114,6 @@ impl<'a> AstValidator<'a> { self.disallow_tilde_const = old; } - fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) { - self.with_tilde_const(None, f) - } - - fn with_banned_tilde_const( - &mut self, - ctx: DisallowTildeConstContext<'a>, - f: impl FnOnce(&mut Self), - ) { - self.with_tilde_const(Some(ctx), f) - } - fn check_type_alias_where_clause_location( &mut self, ty_alias: &TyAlias, @@ -173,7 +165,7 @@ impl<'a> AstValidator<'a> { self.with_impl_trait(Some(t.span), |this| visit::walk_ty(this, t)) } TyKind::TraitObject(..) => self - .with_banned_tilde_const(DisallowTildeConstContext::TraitObject, |this| { + .with_tilde_const(Some(DisallowTildeConstContext::TraitObject), |this| { visit::walk_ty(this, t) }), TyKind::Path(qself, path) => { @@ -229,8 +221,8 @@ impl<'a> AstValidator<'a> { } } - fn err_handler(&self) -> &rustc_errors::Handler { - &self.session.diagnostic() + fn dcx(&self) -> &rustc_errors::DiagCtxt { + self.session.dcx() } fn check_lifetime(&self, ident: Ident) { @@ -278,7 +270,7 @@ impl<'a> AstValidator<'a> { ) { return; } - self.err_handler().emit_err(errors::InvalidUnnamedFieldTy { span, ty_span: ty.span }); + self.dcx().emit_err(errors::InvalidUnnamedFieldTy { span, ty_span: ty.span }); } fn deny_anon_struct_or_union(&self, ty: &Ty) { @@ -287,15 +279,14 @@ impl<'a> AstValidator<'a> { TyKind::AnonUnion(..) => "union", _ => return, }; - self.err_handler() - .emit_err(errors::AnonStructOrUnionNotAllowed { struct_or_union, span: ty.span }); + self.dcx().emit_err(errors::AnonStructOrUnionNotAllowed { struct_or_union, span: ty.span }); } fn deny_unnamed_field(&self, field: &FieldDef) { if let Some(ident) = field.ident && ident.name == kw::Underscore { - self.err_handler() + self.dcx() .emit_err(errors::InvalidUnnamedField { span: field.span, ident_span: ident.span }); } } @@ -401,7 +392,7 @@ impl<'a> AstValidator<'a> { [b0] => b0.span(), [b0, .., bl] => b0.span().to(bl.span()), }; - self.err_handler().emit_err(errors::BoundInContext { span, ctx }); + self.dcx().emit_err(errors::BoundInContext { span, ctx }); } fn check_foreign_ty_genericless( @@ -411,7 +402,7 @@ impl<'a> AstValidator<'a> { after_where_clause: &TyAliasWhereClause, ) { let cannot_have = |span, descr, remove_descr| { - self.err_handler().emit_err(errors::ExternTypesCannotHave { + self.dcx().emit_err(errors::ExternTypesCannotHave { span, descr, remove_descr, @@ -437,7 +428,7 @@ impl<'a> AstValidator<'a> { let Some(body) = body else { return; }; - self.err_handler().emit_err(errors::BodyInExtern { + self.dcx().emit_err(errors::BodyInExtern { span: ident.span, body, block: self.current_extern_span(), @@ -450,7 +441,7 @@ impl<'a> AstValidator<'a> { let Some(body) = body else { return; }; - self.err_handler().emit_err(errors::FnBodyInExtern { + self.dcx().emit_err(errors::FnBodyInExtern { span: ident.span, body: body.span, block: self.current_extern_span(), @@ -464,7 +455,7 @@ impl<'a> AstValidator<'a> { /// An `fn` in `extern { ... }` cannot have qualifiers, e.g. `async fn`. fn check_foreign_fn_headerless(&self, ident: Ident, span: Span, header: FnHeader) { if header.has_qualifiers() { - self.err_handler().emit_err(errors::FnQualifierInExtern { + self.dcx().emit_err(errors::FnQualifierInExtern { span: ident.span, block: self.current_extern_span(), sugg_span: span.until(ident.span.shrink_to_lo()), @@ -475,7 +466,7 @@ impl<'a> AstValidator<'a> { /// An item in `extern { ... }` cannot use non-ascii identifier. fn check_foreign_item_ascii_only(&self, ident: Ident) { if !ident.as_str().is_ascii() { - self.err_handler().emit_err(errors::ExternItemAscii { + self.dcx().emit_err(errors::ExternItemAscii { span: ident.span, block: self.current_extern_span(), }); @@ -504,7 +495,7 @@ impl<'a> AstValidator<'a> { if let Const::Yes(const_span) = header.constness { let mut spans = variadic_spans.clone(); spans.push(const_span); - self.err_handler().emit_err(errors::ConstAndCVariadic { + self.dcx().emit_err(errors::ConstAndCVariadic { spans, const_span, variadic_spans: variadic_spans.clone(), @@ -526,14 +517,14 @@ impl<'a> AstValidator<'a> { _ => {} }; - self.err_handler().emit_err(errors::BadCVariadic { span: variadic_spans }); + self.dcx().emit_err(errors::BadCVariadic { span: variadic_spans }); } fn check_item_named(&self, ident: Ident, kind: &str) { if ident.name != kw::Underscore { return; } - self.err_handler().emit_err(errors::ItemUnderscore { span: ident.span, kind }); + self.dcx().emit_err(errors::ItemUnderscore { span: ident.span, kind }); } fn check_nomangle_item_asciionly(&self, ident: Ident, item_span: Span) { @@ -624,14 +615,14 @@ impl<'a> AstValidator<'a> { let args_len = arg_spans.len(); let constraint_len = constraint_spans.len(); // ...and then error: - self.err_handler().emit_err(errors::ArgsBeforeConstraint { + self.dcx().emit_err(errors::ArgsBeforeConstraint { arg_spans: arg_spans.clone(), constraints: constraint_spans[0], args: *arg_spans.iter().last().unwrap(), data: data.span, constraint_spans: errors::EmptyLabelManySpans(constraint_spans), arg_spans2: errors::EmptyLabelManySpans(arg_spans), - suggestion: self.correct_generic_order_suggestion(&data), + suggestion: self.correct_generic_order_suggestion(data), constraint_len, args_len, }); @@ -676,7 +667,7 @@ impl<'a> AstValidator<'a> { } if !bounds.iter().any(|b| matches!(b, GenericBound::Trait(..))) { - self.err_handler().emit_err(errors::AtLeastOneTrait { span: ty.span }); + self.dcx().emit_err(errors::AtLeastOneTrait { span: ty.span }); } } _ => {} @@ -706,7 +697,7 @@ impl<'a> AstValidator<'a> { /// Checks that generic parameters are in the correct order, /// which is lifetimes, then types and then consts. (`<'a, T, const N: usize>`) fn validate_generic_param_order( - handler: &rustc_errors::Handler, + dcx: &rustc_errors::DiagCtxt, generics: &[GenericParam], span: Span, ) { @@ -747,7 +738,7 @@ fn validate_generic_param_order( if !bounds.is_empty() { ordered_params += ": "; - ordered_params += &pprust::bounds_to_string(&bounds); + ordered_params += &pprust::bounds_to_string(bounds); } match kind { @@ -769,7 +760,7 @@ fn validate_generic_param_order( ordered_params += ">"; for (param_ord, (max_param, spans)) in &out_of_order { - handler.emit_err(errors::OutOfOrderParams { + dcx.emit_err(errors::OutOfOrderParams { spans: spans.clone(), sugg_span: span, param_ord, @@ -832,7 +823,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { errors::VisibilityNotPermittedNote::TraitImpl, ); if let TyKind::Err = self_ty.kind { - this.err_handler().emit_err(errors::ObsoleteAuto { span: item.span }); + this.dcx().emit_err(errors::ObsoleteAuto { span: item.span }); } if let (&Unsafe::Yes(span), &ImplPolarity::Negative(sp)) = (unsafety, polarity) { @@ -845,11 +836,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { this.visit_vis(&item.vis); this.visit_ident(item.ident); - if let Const::Yes(_) = constness { - this.with_tilde_const_allowed(|this| this.visit_generics(generics)); - } else { - this.visit_generics(generics); - } + let disallowed = matches!(constness, Const::No) + .then(|| DisallowTildeConstContext::TraitImpl(item.span)); + this.with_tilde_const(disallowed, |this| this.visit_generics(generics)); this.visit_trait_ref(t); this.visit_ty(self_ty); @@ -863,10 +852,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { polarity, defaultness, constness, - generics: _, + generics, of_trait: None, self_ty, - items: _, + items, }) => { let error = |annotation_span, annotation, only_trait: bool| errors::InherentImplCannot { @@ -882,7 +871,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { errors::VisibilityNotPermittedNote::IndividualImplItems, ); if let &Unsafe::Yes(span) = unsafety { - self.err_handler().emit_err(errors::InherentImplCannotUnsafe { + self.dcx().emit_err(errors::InherentImplCannotUnsafe { span: self_ty.span, annotation_span: span, annotation: "unsafe", @@ -890,14 +879,24 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }); } if let &ImplPolarity::Negative(span) = polarity { - self.err_handler().emit_err(error(span, "negative", false)); + self.dcx().emit_err(error(span, "negative", false)); } if let &Defaultness::Default(def_span) = defaultness { - self.err_handler().emit_err(error(def_span, "`default`", true)); + self.dcx().emit_err(error(def_span, "`default`", true)); } if let &Const::Yes(span) = constness { - self.err_handler().emit_err(error(span, "`const`", true)); + self.dcx().emit_err(error(span, "`const`", true)); } + + self.visit_vis(&item.vis); + self.visit_ident(item.ident); + self.with_tilde_const(Some(DisallowTildeConstContext::Impl(item.span)), |this| { + this.visit_generics(generics) + }); + self.visit_ty(self_ty); + walk_list!(self, visit_assoc_item, items, AssocCtxt::Impl); + walk_list!(self, visit_attribute, &item.attrs); + return; // Avoid visiting again. } ItemKind::Fn(box Fn { defaultness, sig, generics, body }) => { self.check_defaultness(item.span, *defaultness); @@ -940,7 +939,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { errors::VisibilityNotPermittedNote::IndividualForeignItems, ); if let &Unsafe::Yes(span) = unsafety { - self.err_handler().emit_err(errors::UnsafeItem { span, kind: "extern block" }); + self.dcx().emit_err(errors::UnsafeItem { span, kind: "extern block" }); } if abi.is_none() { self.maybe_lint_missing_abi(item.span, item.id); @@ -978,8 +977,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // context for the supertraits. this.visit_vis(&item.vis); this.visit_ident(item.ident); - this.visit_generics(generics); - this.with_tilde_const_allowed(|this| { + let disallowed = + (!is_const_trait).then(|| DisallowTildeConstContext::Trait(item.span)); + this.with_tilde_const(disallowed, |this| { + this.visit_generics(generics); walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits) }); walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait); @@ -989,7 +990,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } ItemKind::Mod(unsafety, mod_kind) => { if let &Unsafe::Yes(span) = unsafety { - self.err_handler().emit_err(errors::UnsafeItem { span, kind: "module" }); + self.dcx().emit_err(errors::UnsafeItem { span, kind: "module" }); } // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584). if !matches!(mod_kind, ModKind::Loaded(_, Inline::Yes, _)) @@ -999,16 +1000,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } ItemKind::Struct(vdata, generics) => match vdata { - // Duplicating the `Visitor` logic allows catching all cases - // of `Anonymous(Struct, Union)` outside of a field struct or union. - // - // Inside `visit_ty` the validator catches every `Anonymous(Struct, Union)` it - // encounters, and only on `ItemKind::Struct` and `ItemKind::Union` - // it uses `visit_ty_common`, which doesn't contain that specific check. - VariantData::Struct(fields, ..) => { + VariantData::Struct { fields, .. } => { self.visit_vis(&item.vis); self.visit_ident(item.ident); self.visit_generics(generics); + // Permit `Anon{Struct,Union}` as field type. walk_list!(self, visit_struct_field_def, fields); walk_list!(self, visit_attribute, &item.attrs); return; @@ -1017,13 +1013,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }, ItemKind::Union(vdata, generics) => { if vdata.fields().is_empty() { - self.err_handler().emit_err(errors::FieldlessUnion { span: item.span }); + self.dcx().emit_err(errors::FieldlessUnion { span: item.span }); } match vdata { - VariantData::Struct(fields, ..) => { + VariantData::Struct { fields, .. } => { self.visit_vis(&item.vis); self.visit_ident(item.ident); self.visit_generics(generics); + // Permit `Anon{Struct,Union}` as field type. walk_list!(self, visit_struct_field_def, fields); walk_list!(self, visit_attribute, &item.attrs); return; @@ -1031,12 +1028,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { _ => {} } } - ItemKind::Const(box ConstItem { defaultness, expr: None, .. }) => { + ItemKind::Const(box ConstItem { defaultness, expr, .. }) => { self.check_defaultness(item.span, *defaultness); - self.session.emit_err(errors::ConstWithoutBody { - span: item.span, - replace_span: self.ending_semi_or_hi(item.span), - }); + if expr.is_none() { + self.session.emit_err(errors::ConstWithoutBody { + span: item.span, + replace_span: self.ending_semi_or_hi(item.span), + }); + } } ItemKind::Static(box StaticItem { expr: None, .. }) => { self.session.emit_err(errors::StaticWithoutBody { @@ -1058,10 +1057,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if self.features.lazy_type_alias { if let Err(err) = self.check_type_alias_where_clause_location(ty_alias) { - self.err_handler().emit_err(err); + self.dcx().emit_err(err); } } else if where_clauses.1.0 { - self.err_handler().emit_err(errors::WhereClauseAfterTypeAlias { + self.dcx().emit_err(errors::WhereClauseAfterTypeAlias { span: where_clauses.1.1, help: self.session.is_nightly_build().then_some(()), }); @@ -1146,14 +1145,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { if let Some(span) = prev_param_default { - self.err_handler().emit_err(errors::GenericDefaultTrailing { span }); + self.dcx().emit_err(errors::GenericDefaultTrailing { span }); break; } } } } - validate_generic_param_order(self.err_handler(), &generics.params, generics.span); + validate_generic_param_order(self.dcx(), &generics.params, generics.span); for predicate in &generics.where_clause.predicates { if let WherePredicate::EqPredicate(predicate) = predicate { @@ -1174,7 +1173,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { match bound { GenericBound::Trait(t, _) => { if !t.bound_generic_params.is_empty() { - self.err_handler() + self.dcx() .emit_err(errors::NestedLifetimes { span: t.span }); } } @@ -1200,39 +1199,50 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if let GenericBound::Trait(poly, modify) = bound { match (ctxt, modify) { (BoundKind::SuperTraits, TraitBoundModifier::Maybe) => { - self.err_handler().emit_err(errors::OptionalTraitSupertrait { + self.dcx().emit_err(errors::OptionalTraitSupertrait { span: poly.span, path_str: pprust::path_to_string(&poly.trait_ref.path), }); } (BoundKind::TraitObject, TraitBoundModifier::Maybe) => { - self.err_handler().emit_err(errors::OptionalTraitObject { span: poly.span }); + self.dcx().emit_err(errors::OptionalTraitObject { span: poly.span }); } - (_, TraitBoundModifier::MaybeConst) + (_, &TraitBoundModifier::MaybeConst(span)) if let Some(reason) = &self.disallow_tilde_const => { let reason = match reason { - DisallowTildeConstContext::TraitObject => { - errors::TildeConstReason::TraitObject - } DisallowTildeConstContext::Fn(FnKind::Closure(..)) => { errors::TildeConstReason::Closure } DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => { errors::TildeConstReason::Function { ident: ident.span } } + &DisallowTildeConstContext::Trait(span) => { + errors::TildeConstReason::Trait { span } + } + &DisallowTildeConstContext::TraitImpl(span) => { + errors::TildeConstReason::TraitImpl { span } + } + &DisallowTildeConstContext::Impl(span) => { + // FIXME(effects): Consider providing a help message or even a structured + // suggestion for moving such bounds to the assoc const fns if available. + errors::TildeConstReason::Impl { span } + } + DisallowTildeConstContext::TraitObject => { + errors::TildeConstReason::TraitObject + } + DisallowTildeConstContext::Item => errors::TildeConstReason::Item, }; - self.err_handler() - .emit_err(errors::TildeConstDisallowed { span: bound.span(), reason }); + self.dcx().emit_err(errors::TildeConstDisallowed { span, reason }); } (_, TraitBoundModifier::MaybeConstMaybe) => { - self.err_handler().emit_err(errors::OptionalConstExclusive { + self.dcx().emit_err(errors::OptionalConstExclusive { span: bound.span(), modifier: "?", }); } (_, TraitBoundModifier::MaybeConstNegative) => { - self.err_handler().emit_err(errors::OptionalConstExclusive { + self.dcx().emit_err(errors::OptionalConstExclusive { span: bound.span(), modifier: "!", }); @@ -1248,7 +1258,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { { for arg in &args.args { if let ast::AngleBracketedArg::Constraint(constraint) = arg { - self.err_handler() + self.dcx() .emit_err(errors::ConstraintOnNegativeBound { span: constraint.span }); } } @@ -1267,14 +1277,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_c_variadic_type(fk); - // Functions cannot both be `const async` + // Functions cannot both be `const async` or `const gen` if let Some(&FnHeader { constness: Const::Yes(cspan), - asyncness: Async::Yes { span: aspan, .. }, + coroutine_kind: Some(coroutine_kind), .. }) = fk.header() { - self.err_handler().emit_err(errors::ConstAndAsync { + let aspan = match coroutine_kind { + CoroutineKind::Async { span: aspan, .. } + | CoroutineKind::Gen { span: aspan, .. } + | CoroutineKind::AsyncGen { span: aspan, .. } => aspan, + }; + // FIXME(gen_blocks): Report a different error for `const gen` + self.dcx().emit_err(errors::ConstAndAsync { spans: vec![cspan, aspan], cspan, aspan, @@ -1314,10 +1330,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } else { match ctxt { - FnCtxt::Foreign => { - self.err_handler().emit_err(errors::PatternInForeign { span }) - } - _ => self.err_handler().emit_err(errors::PatternInBodiless { span }), + FnCtxt::Foreign => self.dcx().emit_err(errors::PatternInForeign { span }), + _ => self.dcx().emit_err(errors::PatternInBodiless { span }), }; } }); @@ -1328,7 +1342,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)) if self.in_const_trait_or_impl); let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk)); - self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk)); } @@ -1397,18 +1410,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } match &item.kind { - AssocItemKind::Type(box TyAlias { generics, bounds, ty, .. }) - if ctxt == AssocCtxt::Trait => - { - self.visit_vis(&item.vis); - self.visit_ident(item.ident); - walk_list!(self, visit_attribute, &item.attrs); - self.with_tilde_const_allowed(|this| { - this.visit_generics(generics); - walk_list!(this, visit_param_bound, bounds, BoundKind::Bound); - }); - walk_list!(self, visit_ty, ty); - } AssocItemKind::Fn(box Fn { sig, generics, body, .. }) if self.in_const_trait_or_impl || ctxt == AssocCtxt::Trait @@ -1461,9 +1462,7 @@ fn deny_equality_constraints( id: rustc_ast::node_id::DUMMY_NODE_ID, ident: *ident, gen_args, - kind: AssocConstraintKind::Equality { - term: predicate.rhs_ty.clone().into(), - }, + kind: AssocConstraintKind::Equality { term: predicate.rhs_ty.clone().into() }, span: ident.span, }); // Add `<Bar = RhsTy>` to `Foo`. @@ -1476,11 +1475,7 @@ fn deny_equality_constraints( }, empty_args => { *empty_args = Some( - AngleBracketedArgs { - span: ident.span, - args: thin_vec![arg], - } - .into(), + AngleBracketedArgs { span: ident.span, args: thin_vec![arg] }.into(), ); } } @@ -1535,7 +1530,7 @@ fn deny_equality_constraints( } } } - this.err_handler().emit_err(err); + this.dcx().emit_err(err); } pub fn check_crate( @@ -1552,7 +1547,7 @@ pub fn check_crate( in_const_trait_or_impl: false, has_proc_macro_decls: false, outer_impl_trait: None, - disallow_tilde_const: None, + disallow_tilde_const: Some(DisallowTildeConstContext::Item), is_impl_trait_banned: false, lint_buffer: lints, }; diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index d14b62d6b..4283fc7c0 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -551,8 +551,6 @@ pub struct TildeConstDisallowed { #[derive(Subdiagnostic)] pub enum TildeConstReason { - #[note(ast_passes_trait)] - TraitObject, #[note(ast_passes_closure)] Closure, #[note(ast_passes_function)] @@ -560,6 +558,25 @@ pub enum TildeConstReason { #[primary_span] ident: Span, }, + #[note(ast_passes_trait)] + Trait { + #[primary_span] + span: Span, + }, + #[note(ast_passes_trait_impl)] + TraitImpl { + #[primary_span] + span: Span, + }, + #[note(ast_passes_impl)] + Impl { + #[primary_span] + span: Span, + }, + #[note(ast_passes_object)] + TraitObject, + #[note(ast_passes_item)] + Item, } #[derive(Diagnostic)] @@ -746,3 +763,12 @@ pub struct AnonStructOrUnionNotAllowed { pub span: Span, pub struct_or_union: &'static str, } + +#[derive(Diagnostic)] +#[diag(ast_passes_match_arm_with_no_body)] +pub struct MatchArmWithNoBody { + #[primary_span] + pub span: Span, + #[suggestion(code = " => todo!(),", applicability = "has-placeholders")] + pub suggestion: Span, +} diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index e1cf0a258..6900d3392 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -88,7 +88,7 @@ impl<'a> PostExpansionVisitor<'a> { } } - match abi::is_enabled(&self.features, span, symbol_unescaped.as_str()) { + match abi::is_enabled(self.features, span, symbol_unescaped.as_str()) { Ok(()) => (), Err(abi::AbiDisabled::Unstable { feature, explain }) => { feature_err_issue( @@ -102,7 +102,7 @@ impl<'a> PostExpansionVisitor<'a> { } Err(abi::AbiDisabled::Unrecognized) => { if self.sess.opts.pretty.map_or(true, |ppm| ppm.needs_hir()) { - self.sess.parse_sess.span_diagnostic.delay_span_bug( + self.sess.dcx().span_delayed_bug( span, format!( "unrecognized ABI not caught in lowering: {}", @@ -182,7 +182,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { .. }) = attr_info { - gate_alt!(self, has_feature(&self.features), *name, attr.span, *descr); + gate_alt!(self, has_feature(self.features), *name, attr.span, *descr); } // Check unstable flavors of the `#[doc]` attribute. if attr.has_name(sym::doc) { @@ -300,7 +300,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ty), .. }) => { - self.check_impl_trait(&ty, false) + self.check_impl_trait(ty, false) } _ => {} @@ -556,6 +556,34 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(generic_const_items, "generic const items are experimental"); gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented"); + if !visitor.features.never_patterns { + if let Some(spans) = spans.get(&sym::never_patterns) { + for &span in spans { + if span.allows_unstable(sym::never_patterns) { + continue; + } + let sm = sess.source_map(); + // We gate two types of spans: the span of a `!` pattern, and the span of a + // match arm without a body. For the latter we want to give the user a normal + // error. + if let Ok(snippet) = sm.span_to_snippet(span) + && snippet == "!" + { + feature_err( + &sess.parse_sess, + sym::never_patterns, + span, + "`!` patterns are experimental", + ) + .emit(); + } else { + let suggestion = span.shrink_to_hi(); + sess.emit_err(errors::MatchArmWithNoBody { span, suggestion }); + } + } + } + } + if !visitor.features.negative_bounds { for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() { sess.emit_err(errors::NegativeBoundUnsupported { span }); @@ -627,7 +655,7 @@ fn maybe_stage_features(sess: &Session, features: &Features, krate: &ast::Crate) if all_stable { err.sugg = Some(attr.span); } - sess.parse_sess.span_diagnostic.emit_err(err); + sess.dcx().emit_err(err); } } } diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs index 5147e672f..ba0918337 100644 --- a/compiler/rustc_ast_passes/src/lib.rs +++ b/compiler/rustc_ast_passes/src/lib.rs @@ -4,9 +4,9 @@ //! //! The crate also contains other misc AST visitors, e.g. `node_count` and `show_span`. -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] +#![allow(internal_features)] +#![doc(rust_logo)] +#![feature(rustdoc_internals)] #![feature(box_patterns)] #![feature(if_let_guard)] #![feature(iter_is_partitioned)] @@ -15,13 +15,10 @@ #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] -use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage}; -use rustc_fluent_macro::fluent_messages; - pub mod ast_validation; mod errors; pub mod feature_gate; pub mod node_count; pub mod show_span; -fluent_messages! { "../messages.ftl" } +rustc_fluent_macro::fluent_messages! { "../messages.ftl" } diff --git a/compiler/rustc_ast_passes/src/show_span.rs b/compiler/rustc_ast_passes/src/show_span.rs index 280cf3284..9882f1d23 100644 --- a/compiler/rustc_ast_passes/src/show_span.rs +++ b/compiler/rustc_ast_passes/src/show_span.rs @@ -31,37 +31,37 @@ impl FromStr for Mode { } struct ShowSpanVisitor<'a> { - span_diagnostic: &'a rustc_errors::Handler, + dcx: &'a rustc_errors::DiagCtxt, mode: Mode, } impl<'a> Visitor<'a> for ShowSpanVisitor<'a> { fn visit_expr(&mut self, e: &'a ast::Expr) { if let Mode::Expression = self.mode { - self.span_diagnostic.emit_warning(errors::ShowSpan { span: e.span, msg: "expression" }); + self.dcx.emit_warning(errors::ShowSpan { span: e.span, msg: "expression" }); } visit::walk_expr(self, e); } fn visit_pat(&mut self, p: &'a ast::Pat) { if let Mode::Pattern = self.mode { - self.span_diagnostic.emit_warning(errors::ShowSpan { span: p.span, msg: "pattern" }); + self.dcx.emit_warning(errors::ShowSpan { span: p.span, msg: "pattern" }); } visit::walk_pat(self, p); } fn visit_ty(&mut self, t: &'a ast::Ty) { if let Mode::Type = self.mode { - self.span_diagnostic.emit_warning(errors::ShowSpan { span: t.span, msg: "type" }); + self.dcx.emit_warning(errors::ShowSpan { span: t.span, msg: "type" }); } visit::walk_ty(self, t); } } -pub fn run(span_diagnostic: &rustc_errors::Handler, mode: &str, krate: &ast::Crate) { +pub fn run(dcx: &rustc_errors::DiagCtxt, mode: &str, krate: &ast::Crate) { let Ok(mode) = mode.parse() else { return; }; - let mut v = ShowSpanVisitor { span_diagnostic, mode }; + let mut v = ShowSpanVisitor { dcx, mode }; visit::walk_crate(&mut v, krate); } |