mirror of
https://github.com/rust-lang/rust
synced 2024-09-18 16:02:39 +00:00
Auto merge of #117204 - nnethercote:rustc_ast_passes, r=compiler-errors
Minor improvements to `rustc_ast_passes` Some improvements I found while looking at this code. r? `@compiler-errors`
This commit is contained in:
commit
62270fb4d6
|
@ -3512,7 +3512,6 @@ dependencies = [
|
||||||
"rustc_span",
|
"rustc_span",
|
||||||
"rustc_target",
|
"rustc_target",
|
||||||
"thin-vec",
|
"thin-vec",
|
||||||
"tracing",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -19,5 +19,4 @@ rustc_session = { path = "../rustc_session" }
|
||||||
rustc_span = { path = "../rustc_span" }
|
rustc_span = { path = "../rustc_span" }
|
||||||
rustc_target = { path = "../rustc_target" }
|
rustc_target = { path = "../rustc_target" }
|
||||||
thin-vec = "0.2.12"
|
thin-vec = "0.2.12"
|
||||||
tracing = "0.1"
|
|
||||||
# tidy-alphabetical-end
|
# tidy-alphabetical-end
|
||||||
|
|
|
@ -1442,15 +1442,14 @@ fn deny_equality_constraints(
|
||||||
let mut err = errors::EqualityInWhere { span: predicate.span, assoc: None, assoc2: None };
|
let mut err = errors::EqualityInWhere { span: predicate.span, assoc: None, assoc2: None };
|
||||||
|
|
||||||
// Given `<A as Foo>::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
|
// Given `<A as Foo>::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
|
||||||
if let TyKind::Path(Some(qself), full_path) = &predicate.lhs_ty.kind {
|
if let TyKind::Path(Some(qself), full_path) = &predicate.lhs_ty.kind
|
||||||
if let TyKind::Path(None, path) = &qself.ty.kind {
|
&& let TyKind::Path(None, path) = &qself.ty.kind
|
||||||
match &path.segments[..] {
|
&& let [PathSegment { ident, args: None, .. }] = &path.segments[..]
|
||||||
[PathSegment { ident, args: None, .. }] => {
|
{
|
||||||
for param in &generics.params {
|
for param in &generics.params {
|
||||||
if param.ident == *ident {
|
if param.ident == *ident
|
||||||
let param = ident;
|
&& let [PathSegment { ident, args, .. }] = &full_path.segments[qself.position..]
|
||||||
match &full_path.segments[qself.position..] {
|
{
|
||||||
[PathSegment { ident, args, .. }] => {
|
|
||||||
// Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
|
// Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
|
||||||
let mut assoc_path = full_path.clone();
|
let mut assoc_path = full_path.clone();
|
||||||
// Remove `Bar` from `Foo::Bar`.
|
// Remove `Bar` from `Foo::Bar`.
|
||||||
|
@ -1488,17 +1487,10 @@ fn deny_equality_constraints(
|
||||||
err.assoc = Some(errors::AssociatedSuggestion {
|
err.assoc = Some(errors::AssociatedSuggestion {
|
||||||
span: predicate.span,
|
span: predicate.span,
|
||||||
ident: *ident,
|
ident: *ident,
|
||||||
param: *param,
|
param: param.ident,
|
||||||
path: pprust::path_to_string(&assoc_path),
|
path: pprust::path_to_string(&assoc_path),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
|
// Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo<Bar = RhsTy>`.
|
||||||
|
|
|
@ -10,53 +10,54 @@
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_target::spec::abi;
|
use rustc_target::spec::abi;
|
||||||
use thin_vec::ThinVec;
|
use thin_vec::ThinVec;
|
||||||
use tracing::debug;
|
|
||||||
|
|
||||||
use crate::errors;
|
use crate::errors;
|
||||||
|
|
||||||
macro_rules! gate_feature_fn {
|
/// The common case.
|
||||||
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => {{
|
macro_rules! gate {
|
||||||
let (visitor, has_feature, span, name, explain, help) =
|
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
|
||||||
(&*$visitor, $has_feature, $span, $name, $explain, $help);
|
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
||||||
let has_feature: bool = has_feature(visitor.features);
|
feature_err(&$visitor.sess.parse_sess, sym::$feature, $span, $explain).emit();
|
||||||
debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
|
|
||||||
if !has_feature && !span.allows_unstable($name) {
|
|
||||||
feature_err(&visitor.sess.parse_sess, name, span, explain).help(help).emit();
|
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
|
($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{
|
||||||
let (visitor, has_feature, span, name, explain) =
|
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
||||||
(&*$visitor, $has_feature, $span, $name, $explain);
|
feature_err(&$visitor.sess.parse_sess, sym::$feature, $span, $explain)
|
||||||
let has_feature: bool = has_feature(visitor.features);
|
.help($help)
|
||||||
debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
|
.emit();
|
||||||
if !has_feature && !span.allows_unstable($name) {
|
|
||||||
feature_err(&visitor.sess.parse_sess, name, span, explain).emit();
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
(future_incompatible; $visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
|
|
||||||
let (visitor, has_feature, span, name, explain) =
|
|
||||||
(&*$visitor, $has_feature, $span, $name, $explain);
|
|
||||||
let has_feature: bool = has_feature(visitor.features);
|
|
||||||
debug!(
|
|
||||||
"gate_feature(feature = {:?}, span = {:?}); has? {} (future_incompatible)",
|
|
||||||
name, span, has_feature
|
|
||||||
);
|
|
||||||
if !has_feature && !span.allows_unstable($name) {
|
|
||||||
feature_warn(&visitor.sess.parse_sess, name, span, explain);
|
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! gate_feature_post {
|
/// The unusual case, where the `has_feature` condition is non-standard.
|
||||||
($visitor: expr, $feature: ident, $span: expr, $explain: expr, $help: expr) => {
|
macro_rules! gate_alt {
|
||||||
gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain, $help)
|
($visitor:expr, $has_feature:expr, $name:expr, $span:expr, $explain:expr) => {{
|
||||||
};
|
if !$has_feature && !$span.allows_unstable($name) {
|
||||||
($visitor: expr, $feature: ident, $span: expr, $explain: expr) => {
|
feature_err(&$visitor.sess.parse_sess, $name, $span, $explain).emit();
|
||||||
gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
|
}
|
||||||
};
|
}};
|
||||||
(future_incompatible; $visitor: expr, $feature: ident, $span: expr, $explain: expr) => {
|
}
|
||||||
gate_feature_fn!(future_incompatible; $visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
|
|
||||||
};
|
/// The case involving a multispan.
|
||||||
|
macro_rules! gate_multi {
|
||||||
|
($visitor:expr, $feature:ident, $spans:expr, $explain:expr) => {{
|
||||||
|
if !$visitor.features.$feature {
|
||||||
|
let spans: Vec<_> =
|
||||||
|
$spans.filter(|span| !span.allows_unstable(sym::$feature)).collect();
|
||||||
|
if !spans.is_empty() {
|
||||||
|
feature_err(&$visitor.sess.parse_sess, sym::$feature, spans, $explain).emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The legacy case.
|
||||||
|
macro_rules! gate_legacy {
|
||||||
|
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
|
||||||
|
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
||||||
|
feature_warn(&$visitor.sess.parse_sess, sym::$feature, $span, $explain);
|
||||||
|
}
|
||||||
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_attribute(attr: &ast::Attribute, sess: &Session, features: &Features) {
|
pub fn check_attribute(attr: &ast::Attribute, sess: &Session, features: &Features) {
|
||||||
|
@ -78,7 +79,7 @@ fn check_abi(&self, abi: ast::StrLit, constness: ast::Const) {
|
||||||
match symbol_unescaped {
|
match symbol_unescaped {
|
||||||
// Stable
|
// Stable
|
||||||
sym::Rust | sym::C => {}
|
sym::Rust | sym::C => {}
|
||||||
abi => gate_feature_post!(
|
abi => gate!(
|
||||||
&self,
|
&self,
|
||||||
const_extern_fn,
|
const_extern_fn,
|
||||||
span,
|
span,
|
||||||
|
@ -129,14 +130,14 @@ impl Visitor<'_> for ImplTraitVisitor<'_> {
|
||||||
fn visit_ty(&mut self, ty: &ast::Ty) {
|
fn visit_ty(&mut self, ty: &ast::Ty) {
|
||||||
if let ast::TyKind::ImplTrait(..) = ty.kind {
|
if let ast::TyKind::ImplTrait(..) = ty.kind {
|
||||||
if self.in_associated_ty {
|
if self.in_associated_ty {
|
||||||
gate_feature_post!(
|
gate!(
|
||||||
&self.vis,
|
&self.vis,
|
||||||
impl_trait_in_assoc_type,
|
impl_trait_in_assoc_type,
|
||||||
ty.span,
|
ty.span,
|
||||||
"`impl Trait` in associated types is unstable"
|
"`impl Trait` in associated types is unstable"
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
gate_feature_post!(
|
gate!(
|
||||||
&self.vis,
|
&self.vis,
|
||||||
type_alias_impl_trait,
|
type_alias_impl_trait,
|
||||||
ty.span,
|
ty.span,
|
||||||
|
@ -153,23 +154,16 @@ fn visit_ty(&mut self, ty: &ast::Ty) {
|
||||||
fn check_late_bound_lifetime_defs(&self, params: &[ast::GenericParam]) {
|
fn check_late_bound_lifetime_defs(&self, params: &[ast::GenericParam]) {
|
||||||
// Check only lifetime parameters are present and that the lifetime
|
// Check only lifetime parameters are present and that the lifetime
|
||||||
// parameters that are present have no bounds.
|
// parameters that are present have no bounds.
|
||||||
let non_lt_param_spans: Vec<_> = params
|
let non_lt_param_spans = params.iter().filter_map(|param| match param.kind {
|
||||||
.iter()
|
|
||||||
.filter_map(|param| match param.kind {
|
|
||||||
ast::GenericParamKind::Lifetime { .. } => None,
|
ast::GenericParamKind::Lifetime { .. } => None,
|
||||||
_ => Some(param.ident.span),
|
_ => Some(param.ident.span),
|
||||||
})
|
});
|
||||||
.collect();
|
gate_multi!(
|
||||||
// FIXME: gate_feature_post doesn't really handle multispans...
|
&self,
|
||||||
if !non_lt_param_spans.is_empty() && !self.features.non_lifetime_binders {
|
non_lifetime_binders,
|
||||||
feature_err(
|
|
||||||
&self.sess.parse_sess,
|
|
||||||
sym::non_lifetime_binders,
|
|
||||||
non_lt_param_spans,
|
non_lt_param_spans,
|
||||||
crate::fluent_generated::ast_passes_forbidden_non_lifetime_param,
|
crate::fluent_generated::ast_passes_forbidden_non_lifetime_param
|
||||||
)
|
);
|
||||||
.emit();
|
|
||||||
}
|
|
||||||
for param in params {
|
for param in params {
|
||||||
if !param.bounds.is_empty() {
|
if !param.bounds.is_empty() {
|
||||||
let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
|
let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
|
||||||
|
@ -188,48 +182,39 @@ fn visit_attribute(&mut self, attr: &ast::Attribute) {
|
||||||
..
|
..
|
||||||
}) = attr_info
|
}) = attr_info
|
||||||
{
|
{
|
||||||
gate_feature_fn!(self, has_feature, attr.span, *name, *descr);
|
gate_alt!(self, has_feature(&self.features), *name, attr.span, *descr);
|
||||||
}
|
}
|
||||||
// Check unstable flavors of the `#[doc]` attribute.
|
// Check unstable flavors of the `#[doc]` attribute.
|
||||||
if attr.has_name(sym::doc) {
|
if attr.has_name(sym::doc) {
|
||||||
for nested_meta in attr.meta_item_list().unwrap_or_default() {
|
for nested_meta in attr.meta_item_list().unwrap_or_default() {
|
||||||
macro_rules! gate_doc { ($($name:ident => $feature:ident)*) => {
|
macro_rules! gate_doc { ($($s:literal { $($name:ident => $feature:ident)* })*) => {
|
||||||
$(if nested_meta.has_name(sym::$name) {
|
$($(if nested_meta.has_name(sym::$name) {
|
||||||
let msg = concat!("`#[doc(", stringify!($name), ")]` is experimental");
|
let msg = concat!("`#[doc(", stringify!($name), ")]` is ", $s);
|
||||||
gate_feature_post!(self, $feature, attr.span, msg);
|
gate!(self, $feature, attr.span, msg);
|
||||||
})*
|
})*)*
|
||||||
}}
|
}}
|
||||||
|
|
||||||
gate_doc!(
|
gate_doc!(
|
||||||
|
"experimental" {
|
||||||
cfg => doc_cfg
|
cfg => doc_cfg
|
||||||
cfg_hide => doc_cfg_hide
|
cfg_hide => doc_cfg_hide
|
||||||
masked => doc_masked
|
masked => doc_masked
|
||||||
notable_trait => doc_notable_trait
|
notable_trait => doc_notable_trait
|
||||||
|
}
|
||||||
|
"meant for internal use only" {
|
||||||
|
keyword => rustdoc_internals
|
||||||
|
fake_variadic => rustdoc_internals
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
if nested_meta.has_name(sym::keyword) {
|
|
||||||
let msg = "`#[doc(keyword)]` is meant for internal use only";
|
|
||||||
gate_feature_post!(self, rustdoc_internals, attr.span, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if nested_meta.has_name(sym::fake_variadic) {
|
|
||||||
let msg = "`#[doc(fake_variadic)]` is meant for internal use only";
|
|
||||||
gate_feature_post!(self, rustdoc_internals, attr.span, msg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !attr.is_doc_comment()
|
if !attr.is_doc_comment()
|
||||||
&& attr.get_normal_item().path.segments.len() == 2
|
&& let [seg, _] = attr.get_normal_item().path.segments.as_slice()
|
||||||
&& attr.get_normal_item().path.segments[0].ident.name == sym::diagnostic
|
&& seg.ident.name == sym::diagnostic
|
||||||
&& !self.features.diagnostic_namespace
|
&& !self.features.diagnostic_namespace
|
||||||
{
|
{
|
||||||
let msg = "`#[diagnostic]` attribute name space is experimental";
|
let msg = "`#[diagnostic]` attribute name space is experimental";
|
||||||
gate_feature_post!(
|
gate!(self, diagnostic_namespace, seg.ident.span, msg);
|
||||||
self,
|
|
||||||
diagnostic_namespace,
|
|
||||||
attr.get_normal_item().path.segments[0].ident.span,
|
|
||||||
msg
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit errors for non-staged-api crates.
|
// Emit errors for non-staged-api crates.
|
||||||
|
@ -255,12 +240,11 @@ fn visit_item(&mut self, i: &'a ast::Item) {
|
||||||
|
|
||||||
ast::ItemKind::Fn(..) => {
|
ast::ItemKind::Fn(..) => {
|
||||||
if attr::contains_name(&i.attrs, sym::start) {
|
if attr::contains_name(&i.attrs, sym::start) {
|
||||||
gate_feature_post!(
|
gate!(
|
||||||
&self,
|
&self,
|
||||||
start,
|
start,
|
||||||
i.span,
|
i.span,
|
||||||
"`#[start]` functions are experimental \
|
"`#[start]` functions are experimental and their signature may change \
|
||||||
and their signature may change \
|
|
||||||
over time"
|
over time"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -270,7 +254,7 @@ fn visit_item(&mut self, i: &'a ast::Item) {
|
||||||
for attr in attr::filter_by_name(&i.attrs, sym::repr) {
|
for attr in attr::filter_by_name(&i.attrs, sym::repr) {
|
||||||
for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) {
|
for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) {
|
||||||
if item.has_name(sym::simd) {
|
if item.has_name(sym::simd) {
|
||||||
gate_feature_post!(
|
gate!(
|
||||||
&self,
|
&self,
|
||||||
repr_simd,
|
repr_simd,
|
||||||
attr.span,
|
attr.span,
|
||||||
|
@ -283,7 +267,7 @@ fn visit_item(&mut self, i: &'a ast::Item) {
|
||||||
|
|
||||||
ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, of_trait, .. }) => {
|
ast::ItemKind::Impl(box ast::Impl { polarity, defaultness, of_trait, .. }) => {
|
||||||
if let &ast::ImplPolarity::Negative(span) = polarity {
|
if let &ast::ImplPolarity::Negative(span) = polarity {
|
||||||
gate_feature_post!(
|
gate!(
|
||||||
&self,
|
&self,
|
||||||
negative_impls,
|
negative_impls,
|
||||||
span.to(of_trait.as_ref().map_or(span, |t| t.path.span)),
|
span.to(of_trait.as_ref().map_or(span, |t| t.path.span)),
|
||||||
|
@ -293,12 +277,12 @@ fn visit_item(&mut self, i: &'a ast::Item) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let ast::Defaultness::Default(_) = defaultness {
|
if let ast::Defaultness::Default(_) = defaultness {
|
||||||
gate_feature_post!(&self, specialization, i.span, "specialization is unstable");
|
gate!(&self, specialization, i.span, "specialization is unstable");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ItemKind::Trait(box ast::Trait { is_auto: ast::IsAuto::Yes, .. }) => {
|
ast::ItemKind::Trait(box ast::Trait { is_auto: ast::IsAuto::Yes, .. }) => {
|
||||||
gate_feature_post!(
|
gate!(
|
||||||
&self,
|
&self,
|
||||||
auto_traits,
|
auto_traits,
|
||||||
i.span,
|
i.span,
|
||||||
|
@ -307,12 +291,12 @@ fn visit_item(&mut self, i: &'a ast::Item) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ItemKind::TraitAlias(..) => {
|
ast::ItemKind::TraitAlias(..) => {
|
||||||
gate_feature_post!(&self, trait_alias, i.span, "trait aliases are experimental");
|
gate!(&self, trait_alias, i.span, "trait aliases are experimental");
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ItemKind::MacroDef(ast::MacroDef { macro_rules: false, .. }) => {
|
ast::ItemKind::MacroDef(ast::MacroDef { macro_rules: false, .. }) => {
|
||||||
let msg = "`macro` is experimental";
|
let msg = "`macro` is experimental";
|
||||||
gate_feature_post!(&self, decl_macro, i.span, msg);
|
gate!(&self, decl_macro, i.span, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ty), .. }) => {
|
ast::ItemKind::TyAlias(box ast::TyAlias { ty: Some(ty), .. }) => {
|
||||||
|
@ -331,7 +315,7 @@ fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
|
||||||
let link_name = attr::first_attr_value_str_by_name(&i.attrs, sym::link_name);
|
let link_name = attr::first_attr_value_str_by_name(&i.attrs, sym::link_name);
|
||||||
let links_to_llvm = link_name.is_some_and(|val| val.as_str().starts_with("llvm."));
|
let links_to_llvm = link_name.is_some_and(|val| val.as_str().starts_with("llvm."));
|
||||||
if links_to_llvm {
|
if links_to_llvm {
|
||||||
gate_feature_post!(
|
gate!(
|
||||||
&self,
|
&self,
|
||||||
link_llvm_intrinsics,
|
link_llvm_intrinsics,
|
||||||
i.span,
|
i.span,
|
||||||
|
@ -340,7 +324,7 @@ fn visit_foreign_item(&mut self, i: &'a ast::ForeignItem) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ForeignItemKind::TyAlias(..) => {
|
ast::ForeignItemKind::TyAlias(..) => {
|
||||||
gate_feature_post!(&self, extern_types, i.span, "extern types are experimental");
|
gate!(&self, extern_types, i.span, "extern types are experimental");
|
||||||
}
|
}
|
||||||
ast::ForeignItemKind::MacCall(..) => {}
|
ast::ForeignItemKind::MacCall(..) => {}
|
||||||
}
|
}
|
||||||
|
@ -356,7 +340,7 @@ fn visit_ty(&mut self, ty: &'a ast::Ty) {
|
||||||
self.check_late_bound_lifetime_defs(&bare_fn_ty.generic_params);
|
self.check_late_bound_lifetime_defs(&bare_fn_ty.generic_params);
|
||||||
}
|
}
|
||||||
ast::TyKind::Never => {
|
ast::TyKind::Never => {
|
||||||
gate_feature_post!(&self, never_type, ty.span, "the `!` type is experimental");
|
gate!(&self, never_type, ty.span, "the `!` type is experimental");
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -389,7 +373,7 @@ fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FnRetTy) {
|
||||||
fn visit_expr(&mut self, e: &'a ast::Expr) {
|
fn visit_expr(&mut self, e: &'a ast::Expr) {
|
||||||
match e.kind {
|
match e.kind {
|
||||||
ast::ExprKind::TryBlock(_) => {
|
ast::ExprKind::TryBlock(_) => {
|
||||||
gate_feature_post!(&self, try_blocks, e.span, "`try` expression is experimental");
|
gate!(&self, try_blocks, e.span, "`try` expression is experimental");
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -405,7 +389,7 @@ fn visit_pat(&mut self, pattern: &'a ast::Pat) {
|
||||||
_ => pat,
|
_ => pat,
|
||||||
};
|
};
|
||||||
if let PatKind::Range(Some(_), None, Spanned { .. }) = inner_pat.kind {
|
if let PatKind::Range(Some(_), None, Spanned { .. }) = inner_pat.kind {
|
||||||
gate_feature_post!(
|
gate!(
|
||||||
&self,
|
&self,
|
||||||
half_open_range_patterns_in_slices,
|
half_open_range_patterns_in_slices,
|
||||||
pat.span,
|
pat.span,
|
||||||
|
@ -415,15 +399,10 @@ fn visit_pat(&mut self, pattern: &'a ast::Pat) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PatKind::Box(..) => {
|
PatKind::Box(..) => {
|
||||||
gate_feature_post!(
|
gate!(&self, box_patterns, pattern.span, "box pattern syntax is experimental");
|
||||||
&self,
|
|
||||||
box_patterns,
|
|
||||||
pattern.span,
|
|
||||||
"box pattern syntax is experimental"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
PatKind::Range(_, Some(_), Spanned { node: RangeEnd::Excluded, .. }) => {
|
PatKind::Range(_, Some(_), Spanned { node: RangeEnd::Excluded, .. }) => {
|
||||||
gate_feature_post!(
|
gate!(
|
||||||
&self,
|
&self,
|
||||||
exclusive_range_pattern,
|
exclusive_range_pattern,
|
||||||
pattern.span,
|
pattern.span,
|
||||||
|
@ -451,7 +430,7 @@ fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {
|
if fn_kind.ctxt() != Some(FnCtxt::Foreign) && fn_kind.decl().c_variadic() {
|
||||||
gate_feature_post!(&self, c_variadic, span, "C-variadic functions are unstable");
|
gate!(&self, c_variadic, span, "C-variadic functions are unstable");
|
||||||
}
|
}
|
||||||
|
|
||||||
visit::walk_fn(self, fn_kind)
|
visit::walk_fn(self, fn_kind)
|
||||||
|
@ -463,14 +442,14 @@ fn visit_assoc_constraint(&mut self, constraint: &'a AssocConstraint) {
|
||||||
&& args.inputs.is_empty()
|
&& args.inputs.is_empty()
|
||||||
&& matches!(args.output, ast::FnRetTy::Default(..))
|
&& matches!(args.output, ast::FnRetTy::Default(..))
|
||||||
{
|
{
|
||||||
gate_feature_post!(
|
gate!(
|
||||||
&self,
|
&self,
|
||||||
return_type_notation,
|
return_type_notation,
|
||||||
constraint.span,
|
constraint.span,
|
||||||
"return type notation is experimental"
|
"return type notation is experimental"
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
gate_feature_post!(
|
gate!(
|
||||||
&self,
|
&self,
|
||||||
associated_type_bounds,
|
associated_type_bounds,
|
||||||
constraint.span,
|
constraint.span,
|
||||||
|
@ -486,7 +465,7 @@ fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
|
||||||
ast::AssocItemKind::Fn(_) => true,
|
ast::AssocItemKind::Fn(_) => true,
|
||||||
ast::AssocItemKind::Type(box ast::TyAlias { ty, .. }) => {
|
ast::AssocItemKind::Type(box ast::TyAlias { ty, .. }) => {
|
||||||
if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
|
if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) {
|
||||||
gate_feature_post!(
|
gate!(
|
||||||
&self,
|
&self,
|
||||||
associated_type_defaults,
|
associated_type_defaults,
|
||||||
i.span,
|
i.span,
|
||||||
|
@ -502,11 +481,11 @@ fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) {
|
||||||
};
|
};
|
||||||
if let ast::Defaultness::Default(_) = i.kind.defaultness() {
|
if let ast::Defaultness::Default(_) = i.kind.defaultness() {
|
||||||
// Limit `min_specialization` to only specializing functions.
|
// Limit `min_specialization` to only specializing functions.
|
||||||
gate_feature_fn!(
|
gate_alt!(
|
||||||
&self,
|
&self,
|
||||||
|x: &Features| x.specialization || (is_fn && x.min_specialization),
|
self.features.specialization || (is_fn && self.features.min_specialization),
|
||||||
i.span,
|
|
||||||
sym::specialization,
|
sym::specialization,
|
||||||
|
i.span,
|
||||||
"specialization is unstable"
|
"specialization is unstable"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -521,17 +500,17 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
||||||
|
|
||||||
let spans = sess.parse_sess.gated_spans.spans.borrow();
|
let spans = sess.parse_sess.gated_spans.spans.borrow();
|
||||||
macro_rules! gate_all {
|
macro_rules! gate_all {
|
||||||
($gate:ident, $msg:literal, $help:literal) => {
|
|
||||||
if let Some(spans) = spans.get(&sym::$gate) {
|
|
||||||
for span in spans {
|
|
||||||
gate_feature_post!(&visitor, $gate, *span, $msg, $help);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
($gate:ident, $msg:literal) => {
|
($gate:ident, $msg:literal) => {
|
||||||
if let Some(spans) = spans.get(&sym::$gate) {
|
if let Some(spans) = spans.get(&sym::$gate) {
|
||||||
for span in spans {
|
for span in spans {
|
||||||
gate_feature_post!(&visitor, $gate, *span, $msg);
|
gate!(&visitor, $gate, *span, $msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($gate:ident, $msg:literal, $help:literal) => {
|
||||||
|
if let Some(spans) = spans.get(&sym::$gate) {
|
||||||
|
for span in spans {
|
||||||
|
gate!(&visitor, $gate, *span, $msg, $help);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -556,7 +535,7 @@ macro_rules! gate_all {
|
||||||
gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental");
|
gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental");
|
||||||
for &span in spans.get(&sym::yield_expr).iter().copied().flatten() {
|
for &span in spans.get(&sym::yield_expr).iter().copied().flatten() {
|
||||||
if !span.at_least_rust_2024() {
|
if !span.at_least_rust_2024() {
|
||||||
gate_feature_post!(&visitor, coroutines, span, "yield syntax is experimental");
|
gate!(&visitor, coroutines, span, "yield syntax is experimental");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gate_all!(gen_blocks, "gen blocks are experimental");
|
gate_all!(gen_blocks, "gen blocks are experimental");
|
||||||
|
@ -590,7 +569,7 @@ macro_rules! gate_all {
|
||||||
macro_rules! gate_all_legacy_dont_use {
|
macro_rules! gate_all_legacy_dont_use {
|
||||||
($gate:ident, $msg:literal) => {
|
($gate:ident, $msg:literal) => {
|
||||||
for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
|
for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
|
||||||
gate_feature_post!(future_incompatible; &visitor, $gate, *span, $msg);
|
gate_legacy!(&visitor, $gate, *span, $msg);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
type B = for<'b, 'a: 'b,> fn(); //~ ERROR lifetime bounds cannot be used in this context
|
type B = for<'b, 'a: 'b,> fn(); //~ ERROR lifetime bounds cannot be used in this context
|
||||||
type C = for<'b, 'a: 'b +> fn(); //~ ERROR lifetime bounds cannot be used in this context
|
type C = for<'b, 'a: 'b +> fn(); //~ ERROR lifetime bounds cannot be used in this context
|
||||||
type D = for<'a, T> fn(); //~ ERROR only lifetime parameters can be used in this context
|
type D = for<'a, T> fn(); //~ ERROR only lifetime parameters can be used in this context
|
||||||
type E = dyn for<T> Fn(); //~ ERROR only lifetime parameters can be used in this context
|
type E = dyn for<T, U> Fn(); //~ ERROR only lifetime parameters can be used in this context
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -28,8 +28,8 @@ LL | type D = for<'a, T> fn();
|
||||||
error[E0658]: only lifetime parameters can be used in this context
|
error[E0658]: only lifetime parameters can be used in this context
|
||||||
--> $DIR/bounds-lifetime.rs:5:18
|
--> $DIR/bounds-lifetime.rs:5:18
|
||||||
|
|
|
|
||||||
LL | type E = dyn for<T> Fn();
|
LL | type E = dyn for<T, U> Fn();
|
||||||
| ^
|
| ^ ^
|
||||||
|
|
|
|
||||||
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
|
= note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
|
||||||
= help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
|
= help: add `#![feature(non_lifetime_binders)]` to the crate attributes to enable
|
||||||
|
|
Loading…
Reference in a new issue