mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
nightly feature tracking: get rid of the per-feature bool fields
This commit is contained in:
parent
e1f3068995
commit
ad3991d303
@ -49,7 +49,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
| asm::InlineAsmArch::RiscV64
|
| asm::InlineAsmArch::RiscV64
|
||||||
| asm::InlineAsmArch::LoongArch64
|
| asm::InlineAsmArch::LoongArch64
|
||||||
);
|
);
|
||||||
if !is_stable && !self.tcx.features().asm_experimental_arch {
|
if !is_stable && !self.tcx.features().asm_experimental_arch() {
|
||||||
feature_err(
|
feature_err(
|
||||||
&self.tcx.sess,
|
&self.tcx.sess,
|
||||||
sym::asm_experimental_arch,
|
sym::asm_experimental_arch,
|
||||||
@ -65,7 +65,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
{
|
{
|
||||||
self.dcx().emit_err(AttSyntaxOnlyX86 { span: sp });
|
self.dcx().emit_err(AttSyntaxOnlyX86 { span: sp });
|
||||||
}
|
}
|
||||||
if asm.options.contains(InlineAsmOptions::MAY_UNWIND) && !self.tcx.features().asm_unwind {
|
if asm.options.contains(InlineAsmOptions::MAY_UNWIND) && !self.tcx.features().asm_unwind() {
|
||||||
feature_err(
|
feature_err(
|
||||||
&self.tcx.sess,
|
&self.tcx.sess,
|
||||||
sym::asm_unwind,
|
sym::asm_unwind,
|
||||||
@ -237,7 +237,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
InlineAsmOperand::Label { block } => {
|
InlineAsmOperand::Label { block } => {
|
||||||
if !self.tcx.features().asm_goto {
|
if !self.tcx.features().asm_goto() {
|
||||||
feature_err(
|
feature_err(
|
||||||
sess,
|
sess,
|
||||||
sym::asm_goto,
|
sym::asm_goto,
|
||||||
|
@ -575,7 +575,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
} else {
|
} else {
|
||||||
// Either `body.is_none()` or `is_never_pattern` here.
|
// Either `body.is_none()` or `is_never_pattern` here.
|
||||||
if !is_never_pattern {
|
if !is_never_pattern {
|
||||||
if self.tcx.features().never_patterns {
|
if self.tcx.features().never_patterns() {
|
||||||
// If the feature is off we already emitted the error after parsing.
|
// If the feature is off we already emitted the error after parsing.
|
||||||
let suggestion = span.shrink_to_hi();
|
let suggestion = span.shrink_to_hi();
|
||||||
self.dcx().emit_err(MatchArmWithNoBody { span, suggestion });
|
self.dcx().emit_err(MatchArmWithNoBody { span, suggestion });
|
||||||
@ -717,7 +717,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
outer_hir_id: HirId,
|
outer_hir_id: HirId,
|
||||||
inner_hir_id: HirId,
|
inner_hir_id: HirId,
|
||||||
) {
|
) {
|
||||||
if self.tcx.features().async_fn_track_caller
|
if self.tcx.features().async_fn_track_caller()
|
||||||
&& let Some(attrs) = self.attrs.get(&outer_hir_id.local_id)
|
&& let Some(attrs) = self.attrs.get(&outer_hir_id.local_id)
|
||||||
&& attrs.into_iter().any(|attr| attr.has_name(sym::track_caller))
|
&& attrs.into_iter().any(|attr| attr.has_name(sym::track_caller))
|
||||||
{
|
{
|
||||||
@ -1572,7 +1572,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
Some(hir::CoroutineKind::Coroutine(_)) => {
|
Some(hir::CoroutineKind::Coroutine(_)) => {
|
||||||
if !self.tcx.features().coroutines {
|
if !self.tcx.features().coroutines() {
|
||||||
rustc_session::parse::feature_err(
|
rustc_session::parse::feature_err(
|
||||||
&self.tcx.sess,
|
&self.tcx.sess,
|
||||||
sym::coroutines,
|
sym::coroutines,
|
||||||
@ -1584,7 +1584,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
if !self.tcx.features().coroutines {
|
if !self.tcx.features().coroutines() {
|
||||||
rustc_session::parse::feature_err(
|
rustc_session::parse::feature_err(
|
||||||
&self.tcx.sess,
|
&self.tcx.sess,
|
||||||
sym::coroutines,
|
sym::coroutines,
|
||||||
|
@ -1512,7 +1512,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let is_param = *is_param.get_or_insert_with(compute_is_param);
|
let is_param = *is_param.get_or_insert_with(compute_is_param);
|
||||||
if !is_param && !self.tcx.features().more_maybe_bounds {
|
if !is_param && !self.tcx.features().more_maybe_bounds() {
|
||||||
self.tcx
|
self.tcx
|
||||||
.sess
|
.sess
|
||||||
.create_feature_err(
|
.create_feature_err(
|
||||||
@ -1530,7 +1530,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
let host_param_parts = if let Const::Yes(span) = constness
|
let host_param_parts = if let Const::Yes(span) = constness
|
||||||
// if this comes from implementing a `const` trait, we must force constness to be appended
|
// if this comes from implementing a `const` trait, we must force constness to be appended
|
||||||
// to the impl item, no matter whether effects is enabled.
|
// to the impl item, no matter whether effects is enabled.
|
||||||
&& (self.tcx.features().effects || force_append_constness)
|
&& (self.tcx.features().effects() || force_append_constness)
|
||||||
{
|
{
|
||||||
let span = self.lower_span(span);
|
let span = self.lower_span(span);
|
||||||
let param_node_id = self.next_node_id();
|
let param_node_id = self.next_node_id();
|
||||||
|
@ -193,7 +193,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
impl_trait_defs: Vec::new(),
|
impl_trait_defs: Vec::new(),
|
||||||
impl_trait_bounds: Vec::new(),
|
impl_trait_bounds: Vec::new(),
|
||||||
allow_try_trait: [sym::try_trait_v2, sym::yeet_desugar_details].into(),
|
allow_try_trait: [sym::try_trait_v2, sym::yeet_desugar_details].into(),
|
||||||
allow_gen_future: if tcx.features().async_fn_track_caller {
|
allow_gen_future: if tcx.features().async_fn_track_caller() {
|
||||||
[sym::gen_future, sym::closure_track_caller].into()
|
[sym::gen_future, sym::closure_track_caller].into()
|
||||||
} else {
|
} else {
|
||||||
[sym::gen_future].into()
|
[sym::gen_future].into()
|
||||||
@ -1035,7 +1035,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
span: data.inputs_span,
|
span: data.inputs_span,
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
if !self.tcx.features().return_type_notation
|
if !self.tcx.features().return_type_notation()
|
||||||
&& self.tcx.sess.is_nightly_build()
|
&& self.tcx.sess.is_nightly_build()
|
||||||
{
|
{
|
||||||
add_feature_diagnostics(
|
add_feature_diagnostics(
|
||||||
@ -1160,7 +1160,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(lt)),
|
ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(lt)),
|
||||||
ast::GenericArg::Type(ty) => {
|
ast::GenericArg::Type(ty) => {
|
||||||
match &ty.kind {
|
match &ty.kind {
|
||||||
TyKind::Infer if self.tcx.features().generic_arg_infer => {
|
TyKind::Infer if self.tcx.features().generic_arg_infer() => {
|
||||||
return GenericArg::Infer(hir::InferArg {
|
return GenericArg::Infer(hir::InferArg {
|
||||||
hir_id: self.lower_node_id(ty.id),
|
hir_id: self.lower_node_id(ty.id),
|
||||||
span: self.lower_span(ty.span),
|
span: self.lower_span(ty.span),
|
||||||
@ -1500,7 +1500,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
// is enabled. We don't check the span of the edition, since this is done
|
// is enabled. We don't check the span of the edition, since this is done
|
||||||
// on a per-opaque basis to account for nested opaques.
|
// on a per-opaque basis to account for nested opaques.
|
||||||
let always_capture_in_scope = match origin {
|
let always_capture_in_scope = match origin {
|
||||||
_ if self.tcx.features().lifetime_capture_rules_2024 => true,
|
_ if self.tcx.features().lifetime_capture_rules_2024() => true,
|
||||||
hir::OpaqueTyOrigin::TyAlias { .. } => true,
|
hir::OpaqueTyOrigin::TyAlias { .. } => true,
|
||||||
hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl, .. } => in_trait_or_impl.is_some(),
|
hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl, .. } => in_trait_or_impl.is_some(),
|
||||||
hir::OpaqueTyOrigin::AsyncFn { .. } => {
|
hir::OpaqueTyOrigin::AsyncFn { .. } => {
|
||||||
@ -1519,7 +1519,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
// Feature gate for RPITIT + use<..>
|
// Feature gate for RPITIT + use<..>
|
||||||
match origin {
|
match origin {
|
||||||
rustc_hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl: Some(_), .. } => {
|
rustc_hir::OpaqueTyOrigin::FnReturn { in_trait_or_impl: Some(_), .. } => {
|
||||||
if !self.tcx.features().precise_capturing_in_traits
|
if !self.tcx.features().precise_capturing_in_traits()
|
||||||
&& let Some(span) = bounds.iter().find_map(|bound| match *bound {
|
&& let Some(span) = bounds.iter().find_map(|bound| match *bound {
|
||||||
ast::GenericBound::Use(_, span) => Some(span),
|
ast::GenericBound::Use(_, span) => Some(span),
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -2270,7 +2270,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen<'hir> {
|
fn lower_array_length(&mut self, c: &AnonConst) -> hir::ArrayLen<'hir> {
|
||||||
match c.value.kind {
|
match c.value.kind {
|
||||||
ExprKind::Underscore => {
|
ExprKind::Underscore => {
|
||||||
if self.tcx.features().generic_arg_infer {
|
if self.tcx.features().generic_arg_infer() {
|
||||||
hir::ArrayLen::Infer(hir::InferArg {
|
hir::ArrayLen::Infer(hir::InferArg {
|
||||||
hir_id: self.lower_node_id(c.id),
|
hir_id: self.lower_node_id(c.id),
|
||||||
span: self.lower_span(c.value.span),
|
span: self.lower_span(c.value.span),
|
||||||
|
@ -268,7 +268,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
span: data.inputs_span,
|
span: data.inputs_span,
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
if !self.tcx.features().return_type_notation
|
if !self.tcx.features().return_type_notation()
|
||||||
&& self.tcx.sess.is_nightly_build()
|
&& self.tcx.sess.is_nightly_build()
|
||||||
{
|
{
|
||||||
add_feature_diagnostics(
|
add_feature_diagnostics(
|
||||||
@ -496,7 +496,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
// // disallowed --^^^^^^^^^^ allowed --^^^^^^^^^^
|
// // disallowed --^^^^^^^^^^ allowed --^^^^^^^^^^
|
||||||
// ```
|
// ```
|
||||||
FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::OpaqueTy { .. }) => {
|
FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::OpaqueTy { .. }) => {
|
||||||
if self.tcx.features().impl_trait_in_fn_trait_return {
|
if self.tcx.features().impl_trait_in_fn_trait_return() {
|
||||||
self.lower_ty(ty, itctx)
|
self.lower_ty(ty, itctx)
|
||||||
} else {
|
} else {
|
||||||
self.lower_ty(
|
self.lower_ty(
|
||||||
|
@ -295,7 +295,8 @@ impl<'a> AstValidator<'a> {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let make_impl_const_sugg = if self.features.const_trait_impl
|
let const_trait_impl = self.features.const_trait_impl();
|
||||||
|
let make_impl_const_sugg = if const_trait_impl
|
||||||
&& let TraitOrTraitImpl::TraitImpl {
|
&& let TraitOrTraitImpl::TraitImpl {
|
||||||
constness: Const::No,
|
constness: Const::No,
|
||||||
polarity: ImplPolarity::Positive,
|
polarity: ImplPolarity::Positive,
|
||||||
@ -308,9 +309,8 @@ impl<'a> AstValidator<'a> {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let make_trait_const_sugg = if self.features.const_trait_impl
|
let make_trait_const_sugg =
|
||||||
&& let TraitOrTraitImpl::Trait { span, constness: None } = parent
|
if const_trait_impl && let TraitOrTraitImpl::Trait { span, constness: None } = parent {
|
||||||
{
|
|
||||||
Some(span.shrink_to_lo())
|
Some(span.shrink_to_lo())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -1145,7 +1145,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
}
|
}
|
||||||
self.check_type_no_bounds(bounds, "this context");
|
self.check_type_no_bounds(bounds, "this context");
|
||||||
|
|
||||||
if self.features.lazy_type_alias {
|
if self.features.lazy_type_alias() {
|
||||||
if let Err(err) = self.check_type_alias_where_clause_location(ty_alias) {
|
if let Err(err) = self.check_type_alias_where_clause_location(ty_alias) {
|
||||||
self.dcx().emit_err(err);
|
self.dcx().emit_err(err);
|
||||||
}
|
}
|
||||||
@ -1286,7 +1286,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
GenericBound::Trait(trait_ref) => {
|
GenericBound::Trait(trait_ref) => {
|
||||||
match (ctxt, trait_ref.modifiers.constness, trait_ref.modifiers.polarity) {
|
match (ctxt, trait_ref.modifiers.constness, trait_ref.modifiers.polarity) {
|
||||||
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_))
|
(BoundKind::SuperTraits, BoundConstness::Never, BoundPolarity::Maybe(_))
|
||||||
if !self.features.more_maybe_bounds =>
|
if !self.features.more_maybe_bounds() =>
|
||||||
{
|
{
|
||||||
self.sess
|
self.sess
|
||||||
.create_feature_err(
|
.create_feature_err(
|
||||||
@ -1299,7 +1299,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
(BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_))
|
(BoundKind::TraitObject, BoundConstness::Never, BoundPolarity::Maybe(_))
|
||||||
if !self.features.more_maybe_bounds =>
|
if !self.features.more_maybe_bounds() =>
|
||||||
{
|
{
|
||||||
self.sess
|
self.sess
|
||||||
.create_feature_err(
|
.create_feature_err(
|
||||||
|
@ -15,13 +15,13 @@ use crate::errors;
|
|||||||
/// The common case.
|
/// The common case.
|
||||||
macro_rules! gate {
|
macro_rules! gate {
|
||||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
|
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
|
||||||
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
if !$visitor.features.$feature() && !$span.allows_unstable(sym::$feature) {
|
||||||
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
#[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
|
||||||
feature_err(&$visitor.sess, sym::$feature, $span, $explain).emit();
|
feature_err(&$visitor.sess, sym::$feature, $span, $explain).emit();
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{
|
($visitor:expr, $feature:ident, $span:expr, $explain:expr, $help:expr) => {{
|
||||||
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
if !$visitor.features.$feature() && !$span.allows_unstable(sym::$feature) {
|
||||||
// FIXME: make this translatable
|
// FIXME: make this translatable
|
||||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||||
#[allow(rustc::untranslatable_diagnostic)]
|
#[allow(rustc::untranslatable_diagnostic)]
|
||||||
@ -43,7 +43,7 @@ macro_rules! gate_alt {
|
|||||||
/// The case involving a multispan.
|
/// The case involving a multispan.
|
||||||
macro_rules! gate_multi {
|
macro_rules! gate_multi {
|
||||||
($visitor:expr, $feature:ident, $spans:expr, $explain:expr) => {{
|
($visitor:expr, $feature:ident, $spans:expr, $explain:expr) => {{
|
||||||
if !$visitor.features.$feature {
|
if !$visitor.features.$feature() {
|
||||||
let spans: Vec<_> =
|
let spans: Vec<_> =
|
||||||
$spans.filter(|span| !span.allows_unstable(sym::$feature)).collect();
|
$spans.filter(|span| !span.allows_unstable(sym::$feature)).collect();
|
||||||
if !spans.is_empty() {
|
if !spans.is_empty() {
|
||||||
@ -56,7 +56,7 @@ macro_rules! gate_multi {
|
|||||||
/// The legacy case.
|
/// The legacy case.
|
||||||
macro_rules! gate_legacy {
|
macro_rules! gate_legacy {
|
||||||
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
|
($visitor:expr, $feature:ident, $span:expr, $explain:expr) => {{
|
||||||
if !$visitor.features.$feature && !$span.allows_unstable(sym::$feature) {
|
if !$visitor.features.$feature() && !$span.allows_unstable(sym::$feature) {
|
||||||
feature_warn(&$visitor.sess, sym::$feature, $span, $explain);
|
feature_warn(&$visitor.sess, sym::$feature, $span, $explain);
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
@ -150,7 +150,7 @@ impl<'a> PostExpansionVisitor<'a> {
|
|||||||
|
|
||||||
// FIXME(non_lifetime_binders): Const bound params are pretty broken.
|
// FIXME(non_lifetime_binders): Const bound params are pretty broken.
|
||||||
// Let's keep users from using this feature accidentally.
|
// Let's keep users from using this feature accidentally.
|
||||||
if self.features.non_lifetime_binders {
|
if self.features.non_lifetime_binders() {
|
||||||
let const_param_spans: Vec<_> = params
|
let const_param_spans: Vec<_> = params
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|param| match param.kind {
|
.filter_map(|param| match param.kind {
|
||||||
@ -210,7 +210,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Emit errors for non-staged-api crates.
|
// Emit errors for non-staged-api crates.
|
||||||
if !self.features.staged_api {
|
if !self.features.staged_api() {
|
||||||
if attr.has_name(sym::unstable)
|
if attr.has_name(sym::unstable)
|
||||||
|| attr.has_name(sym::stable)
|
|| attr.has_name(sym::stable)
|
||||||
|| attr.has_name(sym::rustc_const_unstable)
|
|| attr.has_name(sym::rustc_const_unstable)
|
||||||
@ -470,7 +470,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||||||
// Limit `min_specialization` to only specializing functions.
|
// Limit `min_specialization` to only specializing functions.
|
||||||
gate_alt!(
|
gate_alt!(
|
||||||
&self,
|
&self,
|
||||||
self.features.specialization || (is_fn && self.features.min_specialization),
|
self.features.specialization() || (is_fn && self.features.min_specialization()),
|
||||||
sym::specialization,
|
sym::specialization,
|
||||||
i.span,
|
i.span,
|
||||||
"specialization is unstable"
|
"specialization is unstable"
|
||||||
@ -548,7 +548,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||||||
gate_all!(return_type_notation, "return type notation is experimental");
|
gate_all!(return_type_notation, "return type notation is experimental");
|
||||||
gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
|
gate_all!(pin_ergonomics, "pinned reference syntax is experimental");
|
||||||
|
|
||||||
if !visitor.features.never_patterns {
|
if !visitor.features.never_patterns() {
|
||||||
if let Some(spans) = spans.get(&sym::never_patterns) {
|
if let Some(spans) = spans.get(&sym::never_patterns) {
|
||||||
for &span in spans {
|
for &span in spans {
|
||||||
if span.allows_unstable(sym::never_patterns) {
|
if span.allows_unstable(sym::never_patterns) {
|
||||||
@ -572,7 +572,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !visitor.features.negative_bounds {
|
if !visitor.features.negative_bounds() {
|
||||||
for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() {
|
for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() {
|
||||||
sess.dcx().emit_err(errors::NegativeBoundUnsupported { span });
|
sess.dcx().emit_err(errors::NegativeBoundUnsupported { span });
|
||||||
}
|
}
|
||||||
|
@ -622,7 +622,7 @@ pub fn eval_condition(
|
|||||||
&((
|
&((
|
||||||
if *b { kw::True } else { kw::False },
|
if *b { kw::True } else { kw::False },
|
||||||
sym::cfg_boolean_literals,
|
sym::cfg_boolean_literals,
|
||||||
|features: &Features| features.cfg_boolean_literals,
|
|features: &Features| features.cfg_boolean_literals(),
|
||||||
)),
|
)),
|
||||||
cfg.span(),
|
cfg.span(),
|
||||||
sess,
|
sess,
|
||||||
@ -711,7 +711,7 @@ pub fn eval_condition(
|
|||||||
}
|
}
|
||||||
sym::target => {
|
sym::target => {
|
||||||
if let Some(features) = features
|
if let Some(features) = features
|
||||||
&& !features.cfg_target_compact
|
&& !features.cfg_target_compact()
|
||||||
{
|
{
|
||||||
feature_err(
|
feature_err(
|
||||||
sess,
|
sess,
|
||||||
@ -831,7 +831,7 @@ pub fn find_deprecation(
|
|||||||
attrs: &[Attribute],
|
attrs: &[Attribute],
|
||||||
) -> Option<(Deprecation, Span)> {
|
) -> Option<(Deprecation, Span)> {
|
||||||
let mut depr: Option<(Deprecation, Span)> = None;
|
let mut depr: Option<(Deprecation, Span)> = None;
|
||||||
let is_rustc = features.staged_api;
|
let is_rustc = features.staged_api();
|
||||||
|
|
||||||
'outer: for attr in attrs {
|
'outer: for attr in attrs {
|
||||||
if !attr.has_name(sym::deprecated) {
|
if !attr.has_name(sym::deprecated) {
|
||||||
@ -891,7 +891,7 @@ pub fn find_deprecation(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sym::suggestion => {
|
sym::suggestion => {
|
||||||
if !features.deprecated_suggestion {
|
if !features.deprecated_suggestion() {
|
||||||
sess.dcx().emit_err(
|
sess.dcx().emit_err(
|
||||||
session_diagnostics::DeprecatedItemSuggestion {
|
session_diagnostics::DeprecatedItemSuggestion {
|
||||||
span: mi.span,
|
span: mi.span,
|
||||||
@ -909,7 +909,7 @@ pub fn find_deprecation(
|
|||||||
sess.dcx().emit_err(session_diagnostics::UnknownMetaItem {
|
sess.dcx().emit_err(session_diagnostics::UnknownMetaItem {
|
||||||
span: meta.span(),
|
span: meta.span(),
|
||||||
item: pprust::path_to_string(&mi.path),
|
item: pprust::path_to_string(&mi.path),
|
||||||
expected: if features.deprecated_suggestion {
|
expected: if features.deprecated_suggestion() {
|
||||||
&["since", "note", "suggestion"]
|
&["since", "note", "suggestion"]
|
||||||
} else {
|
} else {
|
||||||
&["since", "note"]
|
&["since", "note"]
|
||||||
|
@ -1035,7 +1035,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||||||
|
|
||||||
fn unsized_feature_enabled(&self) -> bool {
|
fn unsized_feature_enabled(&self) -> bool {
|
||||||
let features = self.tcx().features();
|
let features = self.tcx().features();
|
||||||
features.unsized_locals || features.unsized_fn_params
|
features.unsized_locals() || features.unsized_fn_params()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Equate the inferred type and the annotated type for user type annotations
|
/// Equate the inferred type and the annotated type for user type annotations
|
||||||
|
@ -69,7 +69,7 @@ pub(crate) fn expand_assert<'cx>(
|
|||||||
// If `generic_assert` is enabled, generates rich captured outputs
|
// If `generic_assert` is enabled, generates rich captured outputs
|
||||||
//
|
//
|
||||||
// FIXME(c410-f3r) See https://github.com/rust-lang/rust/issues/96949
|
// FIXME(c410-f3r) See https://github.com/rust-lang/rust/issues/96949
|
||||||
else if cx.ecfg.features.generic_assert {
|
else if cx.ecfg.features.generic_assert() {
|
||||||
context::Context::new(cx, call_site_span).build(cond_expr, panic_path())
|
context::Context::new(cx, call_site_span).build(cond_expr, panic_path())
|
||||||
}
|
}
|
||||||
// If `generic_assert` is not enabled, only outputs a literal "assertion failed: ..."
|
// If `generic_assert` is not enabled, only outputs a literal "assertion failed: ..."
|
||||||
|
@ -137,7 +137,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||||||
let inner = attr.meta_item_list();
|
let inner = attr.meta_item_list();
|
||||||
match inner.as_deref() {
|
match inner.as_deref() {
|
||||||
Some([item]) if item.has_name(sym::linker) => {
|
Some([item]) if item.has_name(sym::linker) => {
|
||||||
if !tcx.features().used_with_arg {
|
if !tcx.features().used_with_arg() {
|
||||||
feature_err(
|
feature_err(
|
||||||
&tcx.sess,
|
&tcx.sess,
|
||||||
sym::used_with_arg,
|
sym::used_with_arg,
|
||||||
@ -149,7 +149,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER;
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER;
|
||||||
}
|
}
|
||||||
Some([item]) if item.has_name(sym::compiler) => {
|
Some([item]) if item.has_name(sym::compiler) => {
|
||||||
if !tcx.features().used_with_arg {
|
if !tcx.features().used_with_arg() {
|
||||||
feature_err(
|
feature_err(
|
||||||
&tcx.sess,
|
&tcx.sess,
|
||||||
sym::used_with_arg,
|
sym::used_with_arg,
|
||||||
@ -213,7 +213,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
if is_closure
|
if is_closure
|
||||||
&& !tcx.features().closure_track_caller
|
&& !tcx.features().closure_track_caller()
|
||||||
&& !attr.span.allows_unstable(sym::closure_track_caller)
|
&& !attr.span.allows_unstable(sym::closure_track_caller)
|
||||||
{
|
{
|
||||||
feature_err(
|
feature_err(
|
||||||
@ -268,7 +268,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||||||
//
|
//
|
||||||
// This exception needs to be kept in sync with allowing
|
// This exception needs to be kept in sync with allowing
|
||||||
// `#[target_feature]` on `main` and `start`.
|
// `#[target_feature]` on `main` and `start`.
|
||||||
} else if !tcx.features().target_feature_11 {
|
} else if !tcx.features().target_feature_11() {
|
||||||
feature_err(
|
feature_err(
|
||||||
&tcx.sess,
|
&tcx.sess,
|
||||||
sym::target_feature_11,
|
sym::target_feature_11,
|
||||||
@ -584,7 +584,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
|
|||||||
// its parent function, which effectively inherits the features anyway. Boxing this closure
|
// its parent function, which effectively inherits the features anyway. Boxing this closure
|
||||||
// would result in this closure being compiled without the inherited target features, but this
|
// would result in this closure being compiled without the inherited target features, but this
|
||||||
// is probably a poor usage of `#[inline(always)]` and easily avoided by not using the attribute.
|
// is probably a poor usage of `#[inline(always)]` and easily avoided by not using the attribute.
|
||||||
if tcx.features().target_feature_11
|
if tcx.features().target_feature_11()
|
||||||
&& tcx.is_closure_like(did.to_def_id())
|
&& tcx.is_closure_like(did.to_def_id())
|
||||||
&& codegen_fn_attrs.inline != InlineAttr::Always
|
&& codegen_fn_attrs.inline != InlineAttr::Always
|
||||||
{
|
{
|
||||||
|
@ -63,27 +63,27 @@ pub(crate) fn from_target_feature(
|
|||||||
|
|
||||||
// Only allow features whose feature gates have been enabled.
|
// Only allow features whose feature gates have been enabled.
|
||||||
let allowed = match feature_gate.as_ref().copied() {
|
let allowed = match feature_gate.as_ref().copied() {
|
||||||
Some(sym::arm_target_feature) => rust_features.arm_target_feature,
|
Some(sym::arm_target_feature) => rust_features.arm_target_feature(),
|
||||||
Some(sym::hexagon_target_feature) => rust_features.hexagon_target_feature,
|
Some(sym::hexagon_target_feature) => rust_features.hexagon_target_feature(),
|
||||||
Some(sym::powerpc_target_feature) => rust_features.powerpc_target_feature,
|
Some(sym::powerpc_target_feature) => rust_features.powerpc_target_feature(),
|
||||||
Some(sym::mips_target_feature) => rust_features.mips_target_feature,
|
Some(sym::mips_target_feature) => rust_features.mips_target_feature(),
|
||||||
Some(sym::riscv_target_feature) => rust_features.riscv_target_feature,
|
Some(sym::riscv_target_feature) => rust_features.riscv_target_feature(),
|
||||||
Some(sym::avx512_target_feature) => rust_features.avx512_target_feature,
|
Some(sym::avx512_target_feature) => rust_features.avx512_target_feature(),
|
||||||
Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature,
|
Some(sym::sse4a_target_feature) => rust_features.sse4a_target_feature(),
|
||||||
Some(sym::tbm_target_feature) => rust_features.tbm_target_feature,
|
Some(sym::tbm_target_feature) => rust_features.tbm_target_feature(),
|
||||||
Some(sym::wasm_target_feature) => rust_features.wasm_target_feature,
|
Some(sym::wasm_target_feature) => rust_features.wasm_target_feature(),
|
||||||
Some(sym::rtm_target_feature) => rust_features.rtm_target_feature,
|
Some(sym::rtm_target_feature) => rust_features.rtm_target_feature(),
|
||||||
Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature,
|
Some(sym::ermsb_target_feature) => rust_features.ermsb_target_feature(),
|
||||||
Some(sym::bpf_target_feature) => rust_features.bpf_target_feature,
|
Some(sym::bpf_target_feature) => rust_features.bpf_target_feature(),
|
||||||
Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature,
|
Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature(),
|
||||||
Some(sym::csky_target_feature) => rust_features.csky_target_feature,
|
Some(sym::csky_target_feature) => rust_features.csky_target_feature(),
|
||||||
Some(sym::loongarch_target_feature) => rust_features.loongarch_target_feature,
|
Some(sym::loongarch_target_feature) => rust_features.loongarch_target_feature(),
|
||||||
Some(sym::lahfsahf_target_feature) => rust_features.lahfsahf_target_feature,
|
Some(sym::lahfsahf_target_feature) => rust_features.lahfsahf_target_feature(),
|
||||||
Some(sym::prfchw_target_feature) => rust_features.prfchw_target_feature,
|
Some(sym::prfchw_target_feature) => rust_features.prfchw_target_feature(),
|
||||||
Some(sym::sha512_sm_x86) => rust_features.sha512_sm_x86,
|
Some(sym::sha512_sm_x86) => rust_features.sha512_sm_x86(),
|
||||||
Some(sym::x86_amx_intrinsics) => rust_features.x86_amx_intrinsics,
|
Some(sym::x86_amx_intrinsics) => rust_features.x86_amx_intrinsics(),
|
||||||
Some(sym::xop_target_feature) => rust_features.xop_target_feature,
|
Some(sym::xop_target_feature) => rust_features.xop_target_feature(),
|
||||||
Some(sym::s390x_target_feature) => rust_features.s390x_target_feature,
|
Some(sym::s390x_target_feature) => rust_features.s390x_target_feature(),
|
||||||
Some(name) => bug!("unknown target feature gate {}", name),
|
Some(name) => bug!("unknown target feature gate {}", name),
|
||||||
None => true,
|
None => true,
|
||||||
};
|
};
|
||||||
|
@ -611,7 +611,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||||||
// the trait into the concrete method, and uses that for const stability
|
// the trait into the concrete method, and uses that for const stability
|
||||||
// checks.
|
// checks.
|
||||||
// FIXME(effects) we might consider moving const stability checks to typeck as well.
|
// FIXME(effects) we might consider moving const stability checks to typeck as well.
|
||||||
if tcx.features().effects {
|
if tcx.features().effects() {
|
||||||
is_trait = true;
|
is_trait = true;
|
||||||
|
|
||||||
if let Ok(Some(instance)) =
|
if let Ok(Some(instance)) =
|
||||||
@ -631,7 +631,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||||||
args: fn_args,
|
args: fn_args,
|
||||||
span: *fn_span,
|
span: *fn_span,
|
||||||
call_source,
|
call_source,
|
||||||
feature: Some(if tcx.features().const_trait_impl {
|
feature: Some(if tcx.features().const_trait_impl() {
|
||||||
sym::effects
|
sym::effects
|
||||||
} else {
|
} else {
|
||||||
sym::const_trait_impl
|
sym::const_trait_impl
|
||||||
|
@ -61,7 +61,7 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> {
|
|||||||
|
|
||||||
pub fn is_const_stable_const_fn(&self) -> bool {
|
pub fn is_const_stable_const_fn(&self) -> bool {
|
||||||
self.const_kind == Some(hir::ConstContext::ConstFn)
|
self.const_kind == Some(hir::ConstContext::ConstFn)
|
||||||
&& self.tcx.features().staged_api
|
&& self.tcx.features().staged_api()
|
||||||
&& is_const_stable_const_fn(self.tcx, self.def_id().to_def_id())
|
&& is_const_stable_const_fn(self.tcx, self.def_id().to_def_id())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ pub fn checking_enabled(ccx: &ConstCx<'_, '_>) -> bool {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ccx.tcx.features().const_precise_live_drops
|
ccx.tcx.features().const_precise_live_drops()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Look for live drops in a const context.
|
/// Look for live drops in a const context.
|
||||||
|
@ -88,7 +88,7 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
|
|||||||
// If the enabled feature is stable, record it.
|
// If the enabled feature is stable, record it.
|
||||||
if let Some(f) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
|
if let Some(f) = ACCEPTED_FEATURES.iter().find(|f| name == f.name) {
|
||||||
let since = Some(Symbol::intern(f.since));
|
let since = Some(Symbol::intern(f.since));
|
||||||
features.set_enabled_lang_feature(name, mi.span(), since, None);
|
features.set_enabled_lang_feature(name, mi.span(), since);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the enabled feature is unstable, record it.
|
// If the enabled feature is unstable, record it.
|
||||||
if let Some(f) = UNSTABLE_FEATURES.iter().find(|f| name == f.feature.name) {
|
if UNSTABLE_FEATURES.iter().find(|f| name == f.feature.name).is_some() {
|
||||||
// When the ICE comes from core, alloc or std (approximation of the standard
|
// When the ICE comes from core, alloc or std (approximation of the standard
|
||||||
// library), there's a chance that the person hitting the ICE may be using
|
// library), there's a chance that the person hitting the ICE may be using
|
||||||
// -Zbuild-std or similar with an untested target. The bug is probably in the
|
// -Zbuild-std or similar with an untested target. The bug is probably in the
|
||||||
@ -114,7 +114,7 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
|
|||||||
{
|
{
|
||||||
sess.using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed);
|
sess.using_internal_features.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
features.set_enabled_lang_feature(name, mi.span(), None, Some(f));
|
features.set_enabled_lang_feature(name, mi.span(), None);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,7 +395,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||||||
/// If attributes are not allowed on expressions, emit an error for `attr`
|
/// If attributes are not allowed on expressions, emit an error for `attr`
|
||||||
#[instrument(level = "trace", skip(self))]
|
#[instrument(level = "trace", skip(self))]
|
||||||
pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
|
pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
|
||||||
if self.features.is_some_and(|features| !features.stmt_expr_attributes)
|
if self.features.is_some_and(|features| !features.stmt_expr_attributes())
|
||||||
&& !attr.span.allows_unstable(sym::stmt_expr_attributes)
|
&& !attr.span.allows_unstable(sym::stmt_expr_attributes)
|
||||||
{
|
{
|
||||||
let mut err = feature_err(
|
let mut err = feature_err(
|
||||||
|
@ -867,7 +867,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||||||
| Annotatable::FieldDef(..)
|
| Annotatable::FieldDef(..)
|
||||||
| Annotatable::Variant(..) => panic!("unexpected annotatable"),
|
| Annotatable::Variant(..) => panic!("unexpected annotatable"),
|
||||||
};
|
};
|
||||||
if self.cx.ecfg.features.proc_macro_hygiene {
|
if self.cx.ecfg.features.proc_macro_hygiene() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
feature_err(
|
feature_err(
|
||||||
@ -905,7 +905,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.cx.ecfg.features.proc_macro_hygiene {
|
if !self.cx.ecfg.features.proc_macro_hygiene() {
|
||||||
annotatable.visit_with(&mut GateProcMacroInput { sess: &self.cx.sess });
|
annotatable.visit_with(&mut GateProcMacroInput { sess: &self.cx.sess });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,14 +121,14 @@ pub(super) fn parse(
|
|||||||
|
|
||||||
/// Asks for the `macro_metavar_expr` feature if it is not enabled
|
/// Asks for the `macro_metavar_expr` feature if it is not enabled
|
||||||
fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &Session, span: Span) {
|
fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &Session, span: Span) {
|
||||||
if !features.macro_metavar_expr {
|
if !features.macro_metavar_expr() {
|
||||||
let msg = "meta-variable expressions are unstable";
|
let msg = "meta-variable expressions are unstable";
|
||||||
feature_err(sess, sym::macro_metavar_expr, span, msg).emit();
|
feature_err(sess, sym::macro_metavar_expr, span, msg).emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_emit_macro_metavar_expr_concat_feature(features: &Features, sess: &Session, span: Span) {
|
fn maybe_emit_macro_metavar_expr_concat_feature(features: &Features, sess: &Session, span: Span) {
|
||||||
if !features.macro_metavar_expr_concat {
|
if !features.macro_metavar_expr_concat() {
|
||||||
let msg = "the `concat` meta-variable expression is unstable";
|
let msg = "the `concat` meta-variable expression is unstable";
|
||||||
feature_err(sess, sym::macro_metavar_expr_concat, span, msg).emit();
|
feature_err(sess, sym::macro_metavar_expr_concat, span, msg).emit();
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ type GateFn = fn(&Features) -> bool;
|
|||||||
|
|
||||||
macro_rules! cfg_fn {
|
macro_rules! cfg_fn {
|
||||||
($field: ident) => {
|
($field: ident) => {
|
||||||
(|features| features.$field) as GateFn
|
Features::$field as GateFn
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1193,7 +1193,7 @@ pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>>
|
|||||||
pub fn is_stable_diagnostic_attribute(sym: Symbol, features: &Features) -> bool {
|
pub fn is_stable_diagnostic_attribute(sym: Symbol, features: &Features) -> bool {
|
||||||
match sym {
|
match sym {
|
||||||
sym::on_unimplemented => true,
|
sym::on_unimplemented => true,
|
||||||
sym::do_not_recommend => features.do_not_recommend,
|
sym::do_not_recommend => features.do_not_recommend(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ use super::{Feature, to_nonzero};
|
|||||||
|
|
||||||
pub struct UnstableFeature {
|
pub struct UnstableFeature {
|
||||||
pub feature: Feature,
|
pub feature: Feature,
|
||||||
set_enabled: fn(&mut Features),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
@ -30,27 +29,14 @@ macro_rules! status_to_enum {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! declare_features {
|
|
||||||
($(
|
|
||||||
$(#[doc = $doc:tt])* ($status:ident, $feature:ident, $ver:expr, $issue:expr),
|
|
||||||
)+) => {
|
|
||||||
/// Unstable language features that are being implemented or being
|
|
||||||
/// considered for acceptance (stabilization) or removal.
|
|
||||||
pub const UNSTABLE_FEATURES: &[UnstableFeature] = &[
|
|
||||||
$(UnstableFeature {
|
|
||||||
feature: Feature {
|
|
||||||
name: sym::$feature,
|
|
||||||
since: $ver,
|
|
||||||
issue: to_nonzero($issue),
|
|
||||||
},
|
|
||||||
// Sets this feature's corresponding bool within `features`.
|
|
||||||
set_enabled: |features| features.$feature = true,
|
|
||||||
}),+
|
|
||||||
];
|
|
||||||
|
|
||||||
const NUM_FEATURES: usize = UNSTABLE_FEATURES.len();
|
|
||||||
|
|
||||||
/// A set of features to be used by later passes.
|
/// A set of features to be used by later passes.
|
||||||
|
///
|
||||||
|
/// There are two ways to check if a language feature `foo` is enabled:
|
||||||
|
/// - Directly with the `foo` method, e.g. `if tcx.features().foo() { ... }`.
|
||||||
|
/// - With the `enabled` method, e.g. `if tcx.features.enabled(sym::foo) { ... }`.
|
||||||
|
///
|
||||||
|
/// The former is preferred. `enabled` should only be used when the feature symbol is not a
|
||||||
|
/// constant, e.g. a parameter, or when the feature is a library feature.
|
||||||
#[derive(Clone, Default, Debug)]
|
#[derive(Clone, Default, Debug)]
|
||||||
pub struct Features {
|
pub struct Features {
|
||||||
/// `#![feature]` attrs for language features, for error reporting.
|
/// `#![feature]` attrs for language features, for error reporting.
|
||||||
@ -59,48 +45,17 @@ macro_rules! declare_features {
|
|||||||
enabled_lib_features: Vec<(Symbol, Span)>,
|
enabled_lib_features: Vec<(Symbol, Span)>,
|
||||||
/// `enabled_lang_features` + `enabled_lib_features`.
|
/// `enabled_lang_features` + `enabled_lib_features`.
|
||||||
enabled_features: FxHashSet<Symbol>,
|
enabled_features: FxHashSet<Symbol>,
|
||||||
/// State of individual features (unstable lang features only).
|
|
||||||
/// This is `true` if and only if the corresponding feature is listed in `enabled_lang_features`.
|
|
||||||
$(
|
|
||||||
$(#[doc = $doc])*
|
|
||||||
pub $feature: bool
|
|
||||||
),+
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Features {
|
impl Features {
|
||||||
pub fn set_enabled_lang_feature(
|
pub fn set_enabled_lang_feature(&mut self, name: Symbol, span: Span, since: Option<Symbol>) {
|
||||||
&mut self,
|
|
||||||
name: Symbol,
|
|
||||||
span: Span,
|
|
||||||
since: Option<Symbol>,
|
|
||||||
feature: Option<&UnstableFeature>,
|
|
||||||
) {
|
|
||||||
self.enabled_lang_features.push((name, span, since));
|
self.enabled_lang_features.push((name, span, since));
|
||||||
self.enabled_features.insert(name);
|
self.enabled_features.insert(name);
|
||||||
if let Some(feature) = feature {
|
|
||||||
assert_eq!(feature.feature.name, name);
|
|
||||||
(feature.set_enabled)(self);
|
|
||||||
} else {
|
|
||||||
// Ensure we don't skip a `set_enabled` call.
|
|
||||||
debug_assert!(UNSTABLE_FEATURES.iter().find(|f| name == f.feature.name).is_none());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_enabled_lib_feature(&mut self, name: Symbol, span: Span) {
|
pub fn set_enabled_lib_feature(&mut self, name: Symbol, span: Span) {
|
||||||
self.enabled_lib_features.push((name, span));
|
self.enabled_lib_features.push((name, span));
|
||||||
self.enabled_features.insert(name);
|
self.enabled_features.insert(name);
|
||||||
// Ensure we don't skip a `set_enabled` call.
|
|
||||||
debug_assert!(UNSTABLE_FEATURES.iter().find(|f| name == f.feature.name).is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This is intended for hashing the set of enabled language features.
|
|
||||||
///
|
|
||||||
/// The expectation is that this produces much smaller code than other alternatives.
|
|
||||||
///
|
|
||||||
/// Note that the total feature count is pretty small, so this is not a huge array.
|
|
||||||
#[inline]
|
|
||||||
pub fn all_lang_features(&self) -> [u8; NUM_FEATURES] {
|
|
||||||
[$(self.$feature as u8),+]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enabled_lang_features(&self) -> &Vec<(Symbol, Span, Option<Symbol>)> {
|
pub fn enabled_lang_features(&self) -> &Vec<(Symbol, Span, Option<Symbol>)> {
|
||||||
@ -117,23 +72,32 @@ macro_rules! declare_features {
|
|||||||
|
|
||||||
/// Is the given feature enabled (via `#[feature(...)]`)?
|
/// Is the given feature enabled (via `#[feature(...)]`)?
|
||||||
pub fn enabled(&self, feature: Symbol) -> bool {
|
pub fn enabled(&self, feature: Symbol) -> bool {
|
||||||
let e = self.enabled_features.contains(&feature);
|
self.enabled_features.contains(&feature)
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
// Ensure this matches `self.$feature`, if that exists.
|
|
||||||
let e2 = match feature {
|
|
||||||
$( sym::$feature => Some(self.$feature), )*
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
if let Some(e2) = e2 {
|
|
||||||
assert_eq!(
|
|
||||||
e, e2,
|
|
||||||
"mismatch in feature state for `{feature}`: \
|
|
||||||
`enabled_features` says {e} but `self.{feature}` says {e2}"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e
|
|
||||||
|
macro_rules! declare_features {
|
||||||
|
($(
|
||||||
|
$(#[doc = $doc:tt])* ($status:ident, $feature:ident, $ver:expr, $issue:expr),
|
||||||
|
)+) => {
|
||||||
|
/// Unstable language features that are being implemented or being
|
||||||
|
/// considered for acceptance (stabilization) or removal.
|
||||||
|
pub const UNSTABLE_FEATURES: &[UnstableFeature] = &[
|
||||||
|
$(UnstableFeature {
|
||||||
|
feature: Feature {
|
||||||
|
name: sym::$feature,
|
||||||
|
since: $ver,
|
||||||
|
issue: to_nonzero($issue),
|
||||||
|
},
|
||||||
|
}),+
|
||||||
|
];
|
||||||
|
|
||||||
|
impl Features {
|
||||||
|
$(
|
||||||
|
pub fn $feature(&self) -> bool {
|
||||||
|
self.enabled_features.contains(&sym::$feature)
|
||||||
}
|
}
|
||||||
|
)*
|
||||||
|
|
||||||
/// Some features are known to be incomplete and using them is likely to have
|
/// Some features are known to be incomplete and using them is likely to have
|
||||||
/// unanticipated results, such as compiler crashes. We warn the user about these
|
/// unanticipated results, such as compiler crashes. We warn the user about these
|
||||||
|
@ -72,7 +72,7 @@ impl<'tcx> Bounds<'tcx> {
|
|||||||
// FIXME(effects): Lift this out of `push_trait_bound`, and move it somewhere else.
|
// FIXME(effects): Lift this out of `push_trait_bound`, and move it somewhere else.
|
||||||
// Perhaps moving this into `lower_poly_trait_ref`, just like we lower associated
|
// Perhaps moving this into `lower_poly_trait_ref`, just like we lower associated
|
||||||
// type bounds.
|
// type bounds.
|
||||||
if !tcx.features().effects {
|
if !tcx.features().effects() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
match predicate_filter {
|
match predicate_filter {
|
||||||
|
@ -1166,7 +1166,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if adt.is_union() && !tcx.features().transparent_unions {
|
if adt.is_union() && !tcx.features().transparent_unions() {
|
||||||
feature_err(
|
feature_err(
|
||||||
&tcx.sess,
|
&tcx.sess,
|
||||||
sym::transparent_unions,
|
sym::transparent_unions,
|
||||||
@ -1301,7 +1301,7 @@ fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||||||
|
|
||||||
let repr_type_ty = def.repr().discr_type().to_ty(tcx);
|
let repr_type_ty = def.repr().discr_type().to_ty(tcx);
|
||||||
if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 {
|
if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 {
|
||||||
if !tcx.features().repr128 {
|
if !tcx.features().repr128() {
|
||||||
feature_err(
|
feature_err(
|
||||||
&tcx.sess,
|
&tcx.sess,
|
||||||
sym::repr128,
|
sym::repr128,
|
||||||
|
@ -167,7 +167,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(tail_expr) = blk.expr {
|
if let Some(tail_expr) = blk.expr {
|
||||||
if visitor.tcx.features().shorter_tail_lifetimes
|
if visitor.tcx.features().shorter_tail_lifetimes()
|
||||||
&& blk.span.edition().at_least_rust_2024()
|
&& blk.span.edition().at_least_rust_2024()
|
||||||
{
|
{
|
||||||
visitor.terminating_scopes.insert(tail_expr.hir_id.local_id);
|
visitor.terminating_scopes.insert(tail_expr.hir_id.local_id);
|
||||||
@ -466,7 +466,8 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
|
|||||||
|
|
||||||
hir::ExprKind::If(cond, then, Some(otherwise)) => {
|
hir::ExprKind::If(cond, then, Some(otherwise)) => {
|
||||||
let expr_cx = visitor.cx;
|
let expr_cx = visitor.cx;
|
||||||
let data = if expr.span.at_least_rust_2024() && visitor.tcx.features().if_let_rescope {
|
let data = if expr.span.at_least_rust_2024() && visitor.tcx.features().if_let_rescope()
|
||||||
|
{
|
||||||
ScopeData::IfThenRescope
|
ScopeData::IfThenRescope
|
||||||
} else {
|
} else {
|
||||||
ScopeData::IfThen
|
ScopeData::IfThen
|
||||||
@ -481,7 +482,8 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h
|
|||||||
|
|
||||||
hir::ExprKind::If(cond, then, None) => {
|
hir::ExprKind::If(cond, then, None) => {
|
||||||
let expr_cx = visitor.cx;
|
let expr_cx = visitor.cx;
|
||||||
let data = if expr.span.at_least_rust_2024() && visitor.tcx.features().if_let_rescope {
|
let data = if expr.span.at_least_rust_2024() && visitor.tcx.features().if_let_rescope()
|
||||||
|
{
|
||||||
ScopeData::IfThenRescope
|
ScopeData::IfThenRescope
|
||||||
} else {
|
} else {
|
||||||
ScopeData::IfThen
|
ScopeData::IfThen
|
||||||
|
@ -110,7 +110,7 @@ where
|
|||||||
|
|
||||||
let mut wfcx = WfCheckingCtxt { ocx, span, body_def_id, param_env };
|
let mut wfcx = WfCheckingCtxt { ocx, span, body_def_id, param_env };
|
||||||
|
|
||||||
if !tcx.features().trivial_bounds {
|
if !tcx.features().trivial_bounds() {
|
||||||
wfcx.check_false_global_bounds()
|
wfcx.check_false_global_bounds()
|
||||||
}
|
}
|
||||||
f(&mut wfcx)?;
|
f(&mut wfcx)?;
|
||||||
@ -921,7 +921,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
|
|||||||
} => {
|
} => {
|
||||||
let ty = tcx.type_of(param.def_id).instantiate_identity();
|
let ty = tcx.type_of(param.def_id).instantiate_identity();
|
||||||
|
|
||||||
if tcx.features().unsized_const_params {
|
if tcx.features().unsized_const_params() {
|
||||||
enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
|
enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
|
||||||
wfcx.register_bound(
|
wfcx.register_bound(
|
||||||
ObligationCause::new(
|
ObligationCause::new(
|
||||||
@ -935,7 +935,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) -> Result<(),
|
|||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
} else if tcx.features().adt_const_params {
|
} else if tcx.features().adt_const_params() {
|
||||||
enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
|
enter_wf_checking_ctxt(tcx, hir_ty.span, param.def_id, |wfcx| {
|
||||||
wfcx.register_bound(
|
wfcx.register_bound(
|
||||||
ObligationCause::new(
|
ObligationCause::new(
|
||||||
@ -1698,9 +1698,9 @@ fn check_method_receiver<'tcx>(
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let arbitrary_self_types_level = if tcx.features().arbitrary_self_types_pointers {
|
let arbitrary_self_types_level = if tcx.features().arbitrary_self_types_pointers() {
|
||||||
Some(ArbitrarySelfTypesLevel::WithPointers)
|
Some(ArbitrarySelfTypesLevel::WithPointers)
|
||||||
} else if tcx.features().arbitrary_self_types {
|
} else if tcx.features().arbitrary_self_types() {
|
||||||
Some(ArbitrarySelfTypesLevel::Basic)
|
Some(ArbitrarySelfTypesLevel::Basic)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -77,7 +77,7 @@ impl<'tcx> InherentCollect<'tcx> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.tcx.features().rustc_attrs {
|
if self.tcx.features().rustc_attrs() {
|
||||||
let items = self.tcx.associated_item_def_ids(impl_def_id);
|
let items = self.tcx.associated_item_def_ids(impl_def_id);
|
||||||
|
|
||||||
if !self.tcx.has_attr(ty_def_id, sym::rustc_has_incoherent_inherent_impls) {
|
if !self.tcx.has_attr(ty_def_id, sym::rustc_has_incoherent_inherent_impls) {
|
||||||
@ -115,7 +115,7 @@ impl<'tcx> InherentCollect<'tcx> {
|
|||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let items = self.tcx.associated_item_def_ids(impl_def_id);
|
let items = self.tcx.associated_item_def_ids(impl_def_id);
|
||||||
if !self.tcx.hir().rustc_coherence_is_core() {
|
if !self.tcx.hir().rustc_coherence_is_core() {
|
||||||
if self.tcx.features().rustc_attrs {
|
if self.tcx.features().rustc_attrs() {
|
||||||
for &impl_item in items {
|
for &impl_item in items {
|
||||||
if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) {
|
if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) {
|
||||||
let span = self.tcx.def_span(impl_def_id);
|
let span = self.tcx.def_span(impl_def_id);
|
||||||
|
@ -53,7 +53,7 @@ fn enforce_trait_manually_implementable(
|
|||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let impl_header_span = tcx.def_span(impl_def_id);
|
let impl_header_span = tcx.def_span(impl_def_id);
|
||||||
|
|
||||||
if tcx.is_lang_item(trait_def_id, LangItem::Freeze) && !tcx.features().freeze_impls {
|
if tcx.is_lang_item(trait_def_id, LangItem::Freeze) && !tcx.features().freeze_impls() {
|
||||||
feature_err(
|
feature_err(
|
||||||
&tcx.sess,
|
&tcx.sess,
|
||||||
sym::freeze_impls,
|
sym::freeze_impls,
|
||||||
@ -86,8 +86,8 @@ fn enforce_trait_manually_implementable(
|
|||||||
|
|
||||||
if let ty::trait_def::TraitSpecializationKind::AlwaysApplicable = trait_def.specialization_kind
|
if let ty::trait_def::TraitSpecializationKind::AlwaysApplicable = trait_def.specialization_kind
|
||||||
{
|
{
|
||||||
if !tcx.features().specialization
|
if !tcx.features().specialization()
|
||||||
&& !tcx.features().min_specialization
|
&& !tcx.features().min_specialization()
|
||||||
&& !impl_header_span.allows_unstable(sym::specialization)
|
&& !impl_header_span.allows_unstable(sym::specialization)
|
||||||
&& !impl_header_span.allows_unstable(sym::min_specialization)
|
&& !impl_header_span.allows_unstable(sym::min_specialization)
|
||||||
{
|
{
|
||||||
|
@ -1129,7 +1129,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar);
|
let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar);
|
||||||
if paren_sugar && !tcx.features().unboxed_closures {
|
if paren_sugar && !tcx.features().unboxed_closures() {
|
||||||
tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span });
|
tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1696,7 +1696,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>(
|
|||||||
|
|
||||||
// Feature gate SIMD types in FFI, since I am not sure that the
|
// Feature gate SIMD types in FFI, since I am not sure that the
|
||||||
// ABIs are handled at all correctly. -huonw
|
// ABIs are handled at all correctly. -huonw
|
||||||
if abi != abi::Abi::RustIntrinsic && !tcx.features().simd_ffi {
|
if abi != abi::Abi::RustIntrinsic && !tcx.features().simd_ffi() {
|
||||||
let check = |hir_ty: &hir::Ty<'_>, ty: Ty<'_>| {
|
let check = |hir_ty: &hir::Ty<'_>, ty: Ty<'_>| {
|
||||||
if ty.is_simd() {
|
if ty.is_simd() {
|
||||||
let snip = tcx
|
let snip = tcx
|
||||||
|
@ -109,7 +109,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
|
|||||||
// We do not allow generic parameters in anon consts if we are inside
|
// We do not allow generic parameters in anon consts if we are inside
|
||||||
// of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed.
|
// of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed.
|
||||||
None
|
None
|
||||||
} else if tcx.features().generic_const_exprs {
|
} else if tcx.features().generic_const_exprs() {
|
||||||
let parent_node = tcx.parent_hir_node(hir_id);
|
let parent_node = tcx.parent_hir_node(hir_id);
|
||||||
debug!(?parent_node);
|
debug!(?parent_node);
|
||||||
if let Node::Variant(Variant { disr_expr: Some(constant), .. }) = parent_node
|
if let Node::Variant(Variant { disr_expr: Some(constant), .. }) = parent_node
|
||||||
|
@ -308,7 +308,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if tcx.features().generic_const_exprs {
|
if tcx.features().generic_const_exprs() {
|
||||||
predicates.extend(const_evaluatable_predicates_of(tcx, def_id));
|
predicates.extend(const_evaluatable_predicates_of(tcx, def_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,7 +524,7 @@ pub(super) fn explicit_predicates_of<'tcx>(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if matches!(def_kind, DefKind::AnonConst)
|
if matches!(def_kind, DefKind::AnonConst)
|
||||||
&& tcx.features().generic_const_exprs
|
&& tcx.features().generic_const_exprs()
|
||||||
&& let Some(defaulted_param_def_id) =
|
&& let Some(defaulted_param_def_id) =
|
||||||
tcx.hir().opt_const_param_default_param_def_id(tcx.local_def_id_to_hir_id(def_id))
|
tcx.hir().opt_const_param_default_param_def_id(tcx.local_def_id_to_hir_id(def_id))
|
||||||
{
|
{
|
||||||
|
@ -1161,7 +1161,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
|
|||||||
&& let Some(param) = generics.params.iter().find(|p| p.def_id == param_id)
|
&& let Some(param) = generics.params.iter().find(|p| p.def_id == param_id)
|
||||||
&& param.is_elided_lifetime()
|
&& param.is_elided_lifetime()
|
||||||
&& !self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id).is_async()
|
&& !self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id).is_async()
|
||||||
&& !self.tcx.features().anonymous_lifetime_in_impl_trait
|
&& !self.tcx.features().anonymous_lifetime_in_impl_trait()
|
||||||
{
|
{
|
||||||
let mut diag: rustc_errors::Diag<'_> = rustc_session::parse::feature_err(
|
let mut diag: rustc_errors::Diag<'_> = rustc_session::parse::feature_err(
|
||||||
&self.tcx.sess,
|
&self.tcx.sess,
|
||||||
@ -2239,7 +2239,7 @@ fn deny_non_region_late_bound(
|
|||||||
format!("late-bound {what} parameter not allowed on {where_}"),
|
format!("late-bound {what} parameter not allowed on {where_}"),
|
||||||
);
|
);
|
||||||
|
|
||||||
let guar = diag.emit_unless(!tcx.features().non_lifetime_binders || !first);
|
let guar = diag.emit_unless(!tcx.features().non_lifetime_binders() || !first);
|
||||||
|
|
||||||
first = false;
|
first = false;
|
||||||
*arg = ResolvedArg::Error(guar);
|
*arg = ResolvedArg::Error(guar);
|
||||||
|
@ -699,7 +699,7 @@ fn infer_placeholder_type<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) {
|
fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) {
|
||||||
if !tcx.features().inherent_associated_types {
|
if !tcx.features().inherent_associated_types() {
|
||||||
use rustc_session::parse::feature_err;
|
use rustc_session::parse::feature_err;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
feature_err(
|
feature_err(
|
||||||
@ -714,7 +714,7 @@ fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) {
|
|||||||
|
|
||||||
pub(crate) fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
|
pub(crate) fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
|
||||||
use hir::intravisit::Visitor;
|
use hir::intravisit::Visitor;
|
||||||
if tcx.features().lazy_type_alias {
|
if tcx.features().lazy_type_alias() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
struct HasTait;
|
struct HasTait;
|
||||||
|
@ -88,7 +88,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
};
|
};
|
||||||
if seen_repeat {
|
if seen_repeat {
|
||||||
self.dcx().emit_err(err);
|
self.dcx().emit_err(err);
|
||||||
} else if !tcx.features().more_maybe_bounds {
|
} else if !tcx.features().more_maybe_bounds() {
|
||||||
self.tcx().sess.create_feature_err(err, sym::more_maybe_bounds).emit();
|
self.tcx().sess.create_feature_err(err, sym::more_maybe_bounds).emit();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
trait_segment: &'_ hir::PathSegment<'_>,
|
trait_segment: &'_ hir::PathSegment<'_>,
|
||||||
is_impl: bool,
|
is_impl: bool,
|
||||||
) {
|
) {
|
||||||
if self.tcx().features().unboxed_closures {
|
if self.tcx().features().unboxed_closures() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,7 +343,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
&& let Some(hir_ty) = constraint.ty()
|
&& let Some(hir_ty) = constraint.ty()
|
||||||
&& let ty = self.lower_ty(hir_ty)
|
&& let ty = self.lower_ty(hir_ty)
|
||||||
&& (ty.is_enum() || ty.references_error())
|
&& (ty.is_enum() || ty.references_error())
|
||||||
&& tcx.features().associated_const_equality
|
&& tcx.features().associated_const_equality()
|
||||||
{
|
{
|
||||||
Some(errors::AssocKindMismatchWrapInBracesSugg {
|
Some(errors::AssocKindMismatchWrapInBracesSugg {
|
||||||
lo: hir_ty.span.shrink_to_lo(),
|
lo: hir_ty.span.shrink_to_lo(),
|
||||||
|
@ -1241,7 +1241,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||||||
// selection during HIR ty lowering instead of in the trait solver), IATs can lead to cycle
|
// selection during HIR ty lowering instead of in the trait solver), IATs can lead to cycle
|
||||||
// errors (#108491) which mask the feature-gate error, needlessly confusing users
|
// errors (#108491) which mask the feature-gate error, needlessly confusing users
|
||||||
// who use IATs by accident (#113265).
|
// who use IATs by accident (#113265).
|
||||||
if !tcx.features().inherent_associated_types {
|
if !tcx.features().inherent_associated_types() {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ pub(crate) fn check_impl_wf(
|
|||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
impl_def_id: LocalDefId,
|
impl_def_id: LocalDefId,
|
||||||
) -> Result<(), ErrorGuaranteed> {
|
) -> Result<(), ErrorGuaranteed> {
|
||||||
let min_specialization = tcx.features().min_specialization;
|
let min_specialization = tcx.features().min_specialization();
|
||||||
let mut res = Ok(());
|
let mut res = Ok(());
|
||||||
debug_assert_matches!(tcx.def_kind(impl_def_id), DefKind::Impl { .. });
|
debug_assert_matches!(tcx.def_kind(impl_def_id), DefKind::Impl { .. });
|
||||||
res = res.and(enforce_impl_params_are_constrained(tcx, impl_def_id));
|
res = res.and(enforce_impl_params_are_constrained(tcx, impl_def_id));
|
||||||
|
@ -116,7 +116,7 @@ fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let extended_abi_support = tcx.features().extended_varargs_abi_support;
|
let extended_abi_support = tcx.features().extended_varargs_abi_support();
|
||||||
let conventions = match (extended_abi_support, abi.supports_varargs()) {
|
let conventions = match (extended_abi_support, abi.supports_varargs()) {
|
||||||
// User enabled additional ABI support for varargs and function ABI matches those ones.
|
// User enabled additional ABI support for varargs and function ABI matches those ones.
|
||||||
(true, true) => return,
|
(true, true) => return,
|
||||||
@ -155,7 +155,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
|||||||
|
|
||||||
// FIXME(effects): remove once effects is implemented in old trait solver
|
// FIXME(effects): remove once effects is implemented in old trait solver
|
||||||
// or if the next solver is stabilized.
|
// or if the next solver is stabilized.
|
||||||
if tcx.features().effects && !tcx.next_trait_solver_globally() {
|
if tcx.features().effects() && !tcx.next_trait_solver_globally() {
|
||||||
tcx.dcx().emit_err(errors::EffectsWithoutNextSolver);
|
tcx.dcx().emit_err(errors::EffectsWithoutNextSolver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +172,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
|
|||||||
let _ = tcx.ensure().crate_inherent_impls_overlap_check(());
|
let _ = tcx.ensure().crate_inherent_impls_overlap_check(());
|
||||||
});
|
});
|
||||||
|
|
||||||
if tcx.features().rustc_attrs {
|
if tcx.features().rustc_attrs() {
|
||||||
tcx.sess.time("outlives_dumping", || outlives::dump::inferred_outlives(tcx));
|
tcx.sess.time("outlives_dumping", || outlives::dump::inferred_outlives(tcx));
|
||||||
tcx.sess.time("variance_dumping", || variance::dump::variances(tcx));
|
tcx.sess.time("variance_dumping", || variance::dump::variances(tcx));
|
||||||
collect::dump::opaque_hidden_types(tcx);
|
collect::dump::opaque_hidden_types(tcx);
|
||||||
|
@ -23,7 +23,7 @@ fn inferred_outlives_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[(ty::Clau
|
|||||||
let crate_map = tcx.inferred_outlives_crate(());
|
let crate_map = tcx.inferred_outlives_crate(());
|
||||||
crate_map.predicates.get(&item_def_id.to_def_id()).copied().unwrap_or(&[])
|
crate_map.predicates.get(&item_def_id.to_def_id()).copied().unwrap_or(&[])
|
||||||
}
|
}
|
||||||
DefKind::AnonConst if tcx.features().generic_const_exprs => {
|
DefKind::AnonConst if tcx.features().generic_const_exprs() => {
|
||||||
let id = tcx.local_def_id_to_hir_id(item_def_id);
|
let id = tcx.local_def_id_to_hir_id(item_def_id);
|
||||||
if tcx.hir().opt_const_param_default_param_def_id(id).is_some() {
|
if tcx.hir().opt_const_param_default_param_def_id(id).is_some() {
|
||||||
// In `generics_of` we set the generics' parent to be our parent's parent which means that
|
// In `generics_of` we set the generics' parent to be our parent's parent which means that
|
||||||
|
@ -721,7 +721,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
|||||||
use rustc_middle::ty::cast::IntTy::*;
|
use rustc_middle::ty::cast::IntTy::*;
|
||||||
|
|
||||||
if self.cast_ty.is_dyn_star() {
|
if self.cast_ty.is_dyn_star() {
|
||||||
if fcx.tcx.features().dyn_star {
|
if fcx.tcx.features().dyn_star() {
|
||||||
span_bug!(self.span, "should be handled by `coerce`");
|
span_bug!(self.span, "should be handled by `coerce`");
|
||||||
} else {
|
} else {
|
||||||
// Report "casting is invalid" rather than "non-primitive cast"
|
// Report "casting is invalid" rather than "non-primitive cast"
|
||||||
|
@ -223,11 +223,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
ty::Ref(r_b, _, mutbl_b) => {
|
ty::Ref(r_b, _, mutbl_b) => {
|
||||||
return self.coerce_borrowed_pointer(a, b, r_b, mutbl_b);
|
return self.coerce_borrowed_pointer(a, b, r_b, mutbl_b);
|
||||||
}
|
}
|
||||||
ty::Dynamic(predicates, region, ty::DynStar) if self.tcx.features().dyn_star => {
|
ty::Dynamic(predicates, region, ty::DynStar) if self.tcx.features().dyn_star() => {
|
||||||
return self.coerce_dyn_star(a, b, predicates, region);
|
return self.coerce_dyn_star(a, b, predicates, region);
|
||||||
}
|
}
|
||||||
ty::Adt(pin, _)
|
ty::Adt(pin, _)
|
||||||
if self.tcx.features().pin_ergonomics
|
if self.tcx.features().pin_ergonomics()
|
||||||
&& self.tcx.is_lang_item(pin.did(), hir::LangItem::Pin) =>
|
&& self.tcx.is_lang_item(pin.did(), hir::LangItem::Pin) =>
|
||||||
{
|
{
|
||||||
return self.coerce_pin(a, b);
|
return self.coerce_pin(a, b);
|
||||||
@ -698,7 +698,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some((sub, sup)) = has_trait_upcasting_coercion
|
if let Some((sub, sup)) = has_trait_upcasting_coercion
|
||||||
&& !self.tcx().features().trait_upcasting
|
&& !self.tcx().features().trait_upcasting()
|
||||||
{
|
{
|
||||||
// Renders better when we erase regions, since they're not really the point here.
|
// Renders better when we erase regions, since they're not really the point here.
|
||||||
let (sub, sup) = self.tcx.erase_regions((sub, sup));
|
let (sub, sup) = self.tcx.erase_regions((sub, sup));
|
||||||
@ -712,7 +712,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
err.emit();
|
err.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion {
|
if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion() {
|
||||||
feature_err(
|
feature_err(
|
||||||
&self.tcx.sess,
|
&self.tcx.sess,
|
||||||
sym::unsized_tuple_coercion,
|
sym::unsized_tuple_coercion,
|
||||||
@ -732,7 +732,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
|||||||
predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||||
b_region: ty::Region<'tcx>,
|
b_region: ty::Region<'tcx>,
|
||||||
) -> CoerceResult<'tcx> {
|
) -> CoerceResult<'tcx> {
|
||||||
if !self.tcx.features().dyn_star {
|
if !self.tcx.features().dyn_star() {
|
||||||
return Err(TypeError::Mismatch);
|
return Err(TypeError::Mismatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1695,7 +1695,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
|||||||
blk_id,
|
blk_id,
|
||||||
expression,
|
expression,
|
||||||
);
|
);
|
||||||
if !fcx.tcx.features().unsized_locals {
|
if !fcx.tcx.features().unsized_locals() {
|
||||||
unsized_return = self.is_return_ty_definitely_unsized(fcx);
|
unsized_return = self.is_return_ty_definitely_unsized(fcx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1709,7 +1709,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
|||||||
return_expr_id,
|
return_expr_id,
|
||||||
expression,
|
expression,
|
||||||
);
|
);
|
||||||
if !fcx.tcx.features().unsized_locals {
|
if !fcx.tcx.features().unsized_locals() {
|
||||||
unsized_return = self.is_return_ty_definitely_unsized(fcx);
|
unsized_return = self.is_return_ty_definitely_unsized(fcx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -735,7 +735,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
// be known if explicitly specified via turbofish).
|
// be known if explicitly specified via turbofish).
|
||||||
self.deferred_transmute_checks.borrow_mut().push((*from, to, expr.hir_id));
|
self.deferred_transmute_checks.borrow_mut().push((*from, to, expr.hir_id));
|
||||||
}
|
}
|
||||||
if !tcx.features().unsized_fn_params {
|
if !tcx.features().unsized_fn_params() {
|
||||||
// We want to remove some Sized bounds from std functions,
|
// We want to remove some Sized bounds from std functions,
|
||||||
// but don't want to expose the removal to stable Rust.
|
// but don't want to expose the removal to stable Rust.
|
||||||
// i.e., we don't want to allow
|
// i.e., we don't want to allow
|
||||||
@ -1996,7 +1996,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
if let Some(base_expr) = base_expr {
|
if let Some(base_expr) = base_expr {
|
||||||
// FIXME: We are currently creating two branches here in order to maintain
|
// FIXME: We are currently creating two branches here in order to maintain
|
||||||
// consistency. But they should be merged as much as possible.
|
// consistency. But they should be merged as much as possible.
|
||||||
let fru_tys = if self.tcx.features().type_changing_struct_update {
|
let fru_tys = if self.tcx.features().type_changing_struct_update() {
|
||||||
if adt.is_struct() {
|
if adt.is_struct() {
|
||||||
// Make some fresh generic parameters for our ADT type.
|
// Make some fresh generic parameters for our ADT type.
|
||||||
let fresh_args = self.fresh_args_for_item(base_expr.span, adt.did());
|
let fresh_args = self.fresh_args_for_item(base_expr.span, adt.did());
|
||||||
@ -3552,7 +3552,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let (ident, _def_scope) =
|
let (ident, _def_scope) =
|
||||||
self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block);
|
self.tcx.adjust_ident_and_get_scope(field, container_def.did(), block);
|
||||||
|
|
||||||
if !self.tcx.features().offset_of_enum {
|
if !self.tcx.features().offset_of_enum() {
|
||||||
rustc_session::parse::feature_err(
|
rustc_session::parse::feature_err(
|
||||||
&self.tcx.sess,
|
&self.tcx.sess,
|
||||||
sym::offset_of_enum,
|
sym::offset_of_enum,
|
||||||
@ -3642,7 +3642,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
{
|
{
|
||||||
let field_ty = self.field_ty(expr.span, field, args);
|
let field_ty = self.field_ty(expr.span, field, args);
|
||||||
|
|
||||||
if self.tcx.features().offset_of_slice {
|
if self.tcx.features().offset_of_slice() {
|
||||||
self.require_type_has_static_alignment(
|
self.require_type_has_static_alignment(
|
||||||
field_ty,
|
field_ty,
|
||||||
expr.span,
|
expr.span,
|
||||||
@ -3675,7 +3675,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
&& field.name == sym::integer(index)
|
&& field.name == sym::integer(index)
|
||||||
{
|
{
|
||||||
if let Some(&field_ty) = tys.get(index) {
|
if let Some(&field_ty) = tys.get(index) {
|
||||||
if self.tcx.features().offset_of_slice {
|
if self.tcx.features().offset_of_slice() {
|
||||||
self.require_type_has_static_alignment(
|
self.require_type_has_static_alignment(
|
||||||
field_ty,
|
field_ty,
|
||||||
expr.span,
|
expr.span,
|
||||||
|
@ -1486,7 +1486,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
return ty::Const::new_error(self.tcx, guar);
|
return ty::Const::new_error(self.tcx, guar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if self.tcx.features().generic_const_exprs {
|
} else if self.tcx.features().generic_const_exprs() {
|
||||||
ct.normalize_internal(self.tcx, self.param_env)
|
ct.normalize_internal(self.tcx, self.param_env)
|
||||||
} else {
|
} else {
|
||||||
ct
|
ct
|
||||||
|
@ -404,7 +404,7 @@ fn default_fallback(tcx: TyCtxt<'_>) -> DivergingFallbackBehavior {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// `feature(never_type_fallback)`: fallback to `!` or `()` trying to not break stuff
|
// `feature(never_type_fallback)`: fallback to `!` or `()` trying to not break stuff
|
||||||
if tcx.features().never_type_fallback {
|
if tcx.features().never_type_fallback() {
|
||||||
return DivergingFallbackBehavior::ContextDependent;
|
return DivergingFallbackBehavior::ContextDependent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
|
|||||||
let var_ty = self.assign(p.span, p.hir_id, None);
|
let var_ty = self.assign(p.span, p.hir_id, None);
|
||||||
|
|
||||||
if let Some((ty_span, hir_id)) = self.outermost_fn_param_pat {
|
if let Some((ty_span, hir_id)) = self.outermost_fn_param_pat {
|
||||||
if !self.fcx.tcx.features().unsized_fn_params {
|
if !self.fcx.tcx.features().unsized_fn_params() {
|
||||||
self.fcx.require_type_is_sized(
|
self.fcx.require_type_is_sized(
|
||||||
var_ty,
|
var_ty,
|
||||||
ty_span,
|
ty_span,
|
||||||
@ -158,7 +158,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if !self.fcx.tcx.features().unsized_locals {
|
} else if !self.fcx.tcx.features().unsized_locals() {
|
||||||
self.fcx.require_type_is_sized(
|
self.fcx.require_type_is_sized(
|
||||||
var_ty,
|
var_ty,
|
||||||
p.span,
|
p.span,
|
||||||
|
@ -161,7 +161,7 @@ fn typeck_with_fallback<'tcx>(
|
|||||||
let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
|
let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig);
|
||||||
let fn_sig = fcx.normalize(body.value.span, fn_sig);
|
let fn_sig = fcx.normalize(body.value.span, fn_sig);
|
||||||
|
|
||||||
check_fn(&mut fcx, fn_sig, None, decl, def_id, body, tcx.features().unsized_fn_params);
|
check_fn(&mut fcx, fn_sig, None, decl, def_id, body, tcx.features().unsized_fn_params());
|
||||||
} else {
|
} else {
|
||||||
let expected_type = infer_type_if_missing(&fcx, node);
|
let expected_type = infer_type_if_missing(&fcx, node);
|
||||||
let expected_type = expected_type.unwrap_or_else(fallback);
|
let expected_type = expected_type.unwrap_or_else(fallback);
|
||||||
|
@ -536,7 +536,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
|||||||
// FIXME(arbitrary_self_types): We probably should limit the
|
// FIXME(arbitrary_self_types): We probably should limit the
|
||||||
// situations where this can occur by adding additional restrictions
|
// situations where this can occur by adding additional restrictions
|
||||||
// to the feature, like the self type can't reference method args.
|
// to the feature, like the self type can't reference method args.
|
||||||
if self.tcx.features().arbitrary_self_types {
|
if self.tcx.features().arbitrary_self_types() {
|
||||||
self.err_ctxt()
|
self.err_ctxt()
|
||||||
.report_mismatched_types(&cause, method_self_ty, self_ty, terr)
|
.report_mismatched_types(&cause, method_self_ty, self_ty, terr)
|
||||||
.emit();
|
.emit();
|
||||||
|
@ -404,7 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
mode,
|
mode,
|
||||||
}));
|
}));
|
||||||
} else if bad_ty.reached_raw_pointer
|
} else if bad_ty.reached_raw_pointer
|
||||||
&& !self.tcx.features().arbitrary_self_types_pointers
|
&& !self.tcx.features().arbitrary_self_types_pointers()
|
||||||
&& !self.tcx.sess.at_least_rust_2018()
|
&& !self.tcx.sess.at_least_rust_2018()
|
||||||
{
|
{
|
||||||
// this case used to be allowed by the compiler,
|
// this case used to be allowed by the compiler,
|
||||||
@ -429,8 +429,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let ty = self.resolve_vars_if_possible(ty.value);
|
let ty = self.resolve_vars_if_possible(ty.value);
|
||||||
let guar = match *ty.kind() {
|
let guar = match *ty.kind() {
|
||||||
ty::Infer(ty::TyVar(_)) => {
|
ty::Infer(ty::TyVar(_)) => {
|
||||||
let raw_ptr_call =
|
let raw_ptr_call = bad_ty.reached_raw_pointer
|
||||||
bad_ty.reached_raw_pointer && !self.tcx.features().arbitrary_self_types;
|
&& !self.tcx.features().arbitrary_self_types();
|
||||||
let mut err = self.err_ctxt().emit_inference_failure_err(
|
let mut err = self.err_ctxt().emit_inference_failure_err(
|
||||||
self.body_id,
|
self.body_id,
|
||||||
span,
|
span,
|
||||||
@ -1146,7 +1146,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ty::Adt(def, args)
|
ty::Adt(def, args)
|
||||||
if self.tcx.features().pin_ergonomics
|
if self.tcx.features().pin_ergonomics()
|
||||||
&& self.tcx.is_lang_item(def.did(), hir::LangItem::Pin) =>
|
&& self.tcx.is_lang_item(def.did(), hir::LangItem::Pin) =>
|
||||||
{
|
{
|
||||||
// make sure this is a pinned reference (and not a `Pin<Box>` or something)
|
// make sure this is a pinned reference (and not a `Pin<Box>` or something)
|
||||||
@ -1195,7 +1195,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
|||||||
self_ty: Ty<'tcx>,
|
self_ty: Ty<'tcx>,
|
||||||
unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
|
unstable_candidates: Option<&mut Vec<(Candidate<'tcx>, Symbol)>>,
|
||||||
) -> Option<PickResult<'tcx>> {
|
) -> Option<PickResult<'tcx>> {
|
||||||
if !self.tcx.features().pin_ergonomics {
|
if !self.tcx.features().pin_ergonomics() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,7 +442,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let features = self.tcx.features();
|
let features = self.tcx.features();
|
||||||
if features.ref_pat_eat_one_layer_2024 || features.ref_pat_eat_one_layer_2024_structural {
|
if features.ref_pat_eat_one_layer_2024() || features.ref_pat_eat_one_layer_2024_structural()
|
||||||
|
{
|
||||||
def_br = def_br.cap_ref_mutability(max_ref_mutbl.as_mutbl());
|
def_br = def_br.cap_ref_mutability(max_ref_mutbl.as_mutbl());
|
||||||
if def_br == ByRef::Yes(Mutability::Not) {
|
if def_br == ByRef::Yes(Mutability::Not) {
|
||||||
max_ref_mutbl = MutblCap::Not;
|
max_ref_mutbl = MutblCap::Not;
|
||||||
@ -490,7 +491,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.tcx.features().string_deref_patterns
|
if self.tcx.features().string_deref_patterns()
|
||||||
&& let hir::ExprKind::Lit(Spanned { node: ast::LitKind::Str(..), .. }) = lt.kind
|
&& let hir::ExprKind::Lit(Spanned { node: ast::LitKind::Str(..), .. }) = lt.kind
|
||||||
{
|
{
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
@ -675,10 +676,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let bm = match user_bind_annot {
|
let bm = match user_bind_annot {
|
||||||
BindingMode(ByRef::No, Mutability::Mut) if matches!(def_br, ByRef::Yes(_)) => {
|
BindingMode(ByRef::No, Mutability::Mut) if matches!(def_br, ByRef::Yes(_)) => {
|
||||||
if pat.span.at_least_rust_2024()
|
if pat.span.at_least_rust_2024()
|
||||||
&& (self.tcx.features().ref_pat_eat_one_layer_2024
|
&& (self.tcx.features().ref_pat_eat_one_layer_2024()
|
||||||
|| self.tcx.features().ref_pat_eat_one_layer_2024_structural)
|
|| self.tcx.features().ref_pat_eat_one_layer_2024_structural())
|
||||||
{
|
{
|
||||||
if !self.tcx.features().mut_ref {
|
if !self.tcx.features().mut_ref() {
|
||||||
feature_err(
|
feature_err(
|
||||||
&self.tcx.sess,
|
&self.tcx.sess,
|
||||||
sym::mut_ref,
|
sym::mut_ref,
|
||||||
@ -2152,8 +2153,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
) -> Ty<'tcx> {
|
) -> Ty<'tcx> {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let features = tcx.features();
|
let features = tcx.features();
|
||||||
let ref_pat_eat_one_layer_2024 = features.ref_pat_eat_one_layer_2024;
|
let ref_pat_eat_one_layer_2024 = features.ref_pat_eat_one_layer_2024();
|
||||||
let ref_pat_eat_one_layer_2024_structural = features.ref_pat_eat_one_layer_2024_structural;
|
let ref_pat_eat_one_layer_2024_structural =
|
||||||
|
features.ref_pat_eat_one_layer_2024_structural();
|
||||||
|
|
||||||
let no_ref_mut_behind_and =
|
let no_ref_mut_behind_and =
|
||||||
ref_pat_eat_one_layer_2024 || ref_pat_eat_one_layer_2024_structural;
|
ref_pat_eat_one_layer_2024 || ref_pat_eat_one_layer_2024_structural;
|
||||||
|
@ -488,7 +488,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let final_upvar_tys = self.final_upvar_tys(closure_def_id);
|
let final_upvar_tys = self.final_upvar_tys(closure_def_id);
|
||||||
debug!(?closure_hir_id, ?args, ?final_upvar_tys);
|
debug!(?closure_hir_id, ?args, ?final_upvar_tys);
|
||||||
|
|
||||||
if self.tcx.features().unsized_locals || self.tcx.features().unsized_fn_params {
|
if self.tcx.features().unsized_locals() || self.tcx.features().unsized_fn_params() {
|
||||||
for capture in
|
for capture in
|
||||||
self.typeck_results.borrow().closure_min_captures_flattened(closure_def_id)
|
self.typeck_results.borrow().closure_min_captures_flattened(closure_def_id)
|
||||||
{
|
{
|
||||||
|
@ -830,7 +830,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
|
|||||||
value = tcx.fold_regions(value, |_, _| tcx.lifetimes.re_erased);
|
value = tcx.fold_regions(value, |_, _| tcx.lifetimes.re_erased);
|
||||||
|
|
||||||
// Normalize consts in writeback, because GCE doesn't normalize eagerly.
|
// Normalize consts in writeback, because GCE doesn't normalize eagerly.
|
||||||
if tcx.features().generic_const_exprs {
|
if tcx.features().generic_const_exprs() {
|
||||||
value =
|
value =
|
||||||
value.fold_with(&mut EagerlyNormalizeConsts { tcx, param_env: self.fcx.param_env });
|
value.fold_with(&mut EagerlyNormalizeConsts { tcx, param_env: self.fcx.param_env });
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ pub(crate) fn assert_dep_graph(tcx: TyCtxt<'_>) {
|
|||||||
// if the `rustc_attrs` feature is not enabled, then the
|
// if the `rustc_attrs` feature is not enabled, then the
|
||||||
// attributes we are interested in cannot be present anyway, so
|
// attributes we are interested in cannot be present anyway, so
|
||||||
// skip the walk.
|
// skip the walk.
|
||||||
if !tcx.features().rustc_attrs {
|
if !tcx.features().rustc_attrs() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ pub(crate) fn check_dirty_clean_annotations(tcx: TyCtxt<'_>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// can't add `#[rustc_clean]` etc without opting into this feature
|
// can't add `#[rustc_clean]` etc without opting into this feature
|
||||||
if !tcx.features().rustc_attrs {
|
if !tcx.features().rustc_attrs() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ impl<'tcx> LateLintPass<'tcx> for AsyncFnInTrait {
|
|||||||
&& let hir::IsAsync::Async(async_span) = sig.header.asyncness
|
&& let hir::IsAsync::Async(async_span) = sig.header.asyncness
|
||||||
{
|
{
|
||||||
// RTN can be used to bound `async fn` in traits in a better way than "always"
|
// RTN can be used to bound `async fn` in traits in a better way than "always"
|
||||||
if cx.tcx.features().return_type_notation {
|
if cx.tcx.features().return_type_notation() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1235,7 +1235,7 @@ impl<'tcx> LateLintPass<'tcx> for UngatedAsyncFnTrackCaller {
|
|||||||
def_id: LocalDefId,
|
def_id: LocalDefId,
|
||||||
) {
|
) {
|
||||||
if fn_kind.asyncness().is_async()
|
if fn_kind.asyncness().is_async()
|
||||||
&& !cx.tcx.features().async_fn_track_caller
|
&& !cx.tcx.features().async_fn_track_caller()
|
||||||
// Now, check if the function has the `#[track_caller]` attribute
|
// Now, check if the function has the `#[track_caller]` attribute
|
||||||
&& let Some(attr) = cx.tcx.get_attr(def_id, sym::track_caller)
|
&& let Some(attr) = cx.tcx.get_attr(def_id, sym::track_caller)
|
||||||
{
|
{
|
||||||
@ -1424,7 +1424,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
|
|||||||
// See also `tests/ui/const-generics/generic_const_exprs/type-alias-bounds.rs`.
|
// See also `tests/ui/const-generics/generic_const_exprs/type-alias-bounds.rs`.
|
||||||
let ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
|
let ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
|
||||||
if ty.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION)
|
if ty.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION)
|
||||||
&& cx.tcx.features().generic_const_exprs
|
&& cx.tcx.features().generic_const_exprs()
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1538,7 +1538,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
|
|||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) {
|
||||||
use rustc_middle::ty::ClauseKind;
|
use rustc_middle::ty::ClauseKind;
|
||||||
|
|
||||||
if cx.tcx.features().trivial_bounds {
|
if cx.tcx.features().trivial_bounds() {
|
||||||
let predicates = cx.tcx.predicates_of(item.owner_id);
|
let predicates = cx.tcx.predicates_of(item.owner_id);
|
||||||
for &(predicate, span) in predicates.predicates {
|
for &(predicate, span) in predicates.predicates {
|
||||||
let predicate_kind_name = match predicate.kind().skip_binder() {
|
let predicate_kind_name = match predicate.kind().skip_binder() {
|
||||||
|
@ -243,7 +243,7 @@ impl_lint_pass!(
|
|||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for IfLetRescope {
|
impl<'tcx> LateLintPass<'tcx> for IfLetRescope {
|
||||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
|
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
|
||||||
if expr.span.edition().at_least_rust_2024() || !cx.tcx.features().if_let_rescope {
|
if expr.span.edition().at_least_rust_2024() || !cx.tcx.features().if_let_rescope() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let (Level::Allow, _) = cx.tcx.lint_level_at_node(IF_LET_RESCOPE, expr.hir_id) {
|
if let (Level::Allow, _) = cx.tcx.lint_level_at_node(IF_LET_RESCOPE, expr.hir_id) {
|
||||||
|
@ -263,8 +263,8 @@ where
|
|||||||
&& parent == self.parent_def_id
|
&& parent == self.parent_def_id
|
||||||
{
|
{
|
||||||
let opaque_span = self.tcx.def_span(opaque_def_id);
|
let opaque_span = self.tcx.def_span(opaque_def_id);
|
||||||
let new_capture_rules =
|
let new_capture_rules = opaque_span.at_least_rust_2024()
|
||||||
opaque_span.at_least_rust_2024() || self.tcx.features().lifetime_capture_rules_2024;
|
|| self.tcx.features().lifetime_capture_rules_2024();
|
||||||
if !new_capture_rules
|
if !new_capture_rules
|
||||||
&& !opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..)))
|
&& !opaque.bounds.iter().any(|bound| matches!(bound, hir::GenericBound::Use(..)))
|
||||||
{
|
{
|
||||||
|
@ -137,7 +137,7 @@ impl<'tcx> LateLintPass<'tcx> for TailExprDropOrder {
|
|||||||
_: Span,
|
_: Span,
|
||||||
def_id: rustc_span::def_id::LocalDefId,
|
def_id: rustc_span::def_id::LocalDefId,
|
||||||
) {
|
) {
|
||||||
if cx.tcx.sess.at_least_rust_2024() && cx.tcx.features().shorter_tail_lifetimes {
|
if cx.tcx.sess.at_least_rust_2024() && cx.tcx.features().shorter_tail_lifetimes() {
|
||||||
Self::check_fn_or_closure(cx, fn_kind, body, def_id);
|
Self::check_fn_or_closure(cx, fn_kind, body, def_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
|
|||||||
|
|
||||||
let mut upstream_in_dylibs = FxHashSet::default();
|
let mut upstream_in_dylibs = FxHashSet::default();
|
||||||
|
|
||||||
if tcx.features().rustc_private {
|
if tcx.features().rustc_private() {
|
||||||
// We need this to prevent users of `rustc_driver` from linking dynamically to `std`
|
// We need this to prevent users of `rustc_driver` from linking dynamically to `std`
|
||||||
// which does not work as `std` is also statically linked into `rustc_driver`.
|
// which does not work as `std` is also statically linked into `rustc_driver`.
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ impl<'tcx> Collector<'tcx> {
|
|||||||
NativeLibKind::RawDylib
|
NativeLibKind::RawDylib
|
||||||
}
|
}
|
||||||
"link-arg" => {
|
"link-arg" => {
|
||||||
if !features.link_arg_attribute {
|
if !features.link_arg_attribute() {
|
||||||
feature_err(
|
feature_err(
|
||||||
sess,
|
sess,
|
||||||
sym::link_arg_attribute,
|
sym::link_arg_attribute,
|
||||||
@ -314,7 +314,7 @@ impl<'tcx> Collector<'tcx> {
|
|||||||
.emit_err(errors::LinkCfgSinglePredicate { span: item.span() });
|
.emit_err(errors::LinkCfgSinglePredicate { span: item.span() });
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
if !features.link_cfg {
|
if !features.link_cfg() {
|
||||||
feature_err(
|
feature_err(
|
||||||
sess,
|
sess,
|
||||||
sym::link_cfg,
|
sym::link_cfg,
|
||||||
@ -384,7 +384,7 @@ impl<'tcx> Collector<'tcx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
macro report_unstable_modifier($feature: ident) {
|
macro report_unstable_modifier($feature: ident) {
|
||||||
if !features.$feature {
|
if !features.$feature() {
|
||||||
// FIXME: make this translatable
|
// FIXME: make this translatable
|
||||||
#[expect(rustc::untranslatable_diagnostic)]
|
#[expect(rustc::untranslatable_diagnostic)]
|
||||||
feature_err(
|
feature_err(
|
||||||
|
@ -1765,7 +1765,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||||||
fn encode_stability(&mut self, def_id: DefId) {
|
fn encode_stability(&mut self, def_id: DefId) {
|
||||||
// The query lookup can take a measurable amount of time in crates with many items. Check if
|
// The query lookup can take a measurable amount of time in crates with many items. Check if
|
||||||
// the stability attributes are even enabled before using their queries.
|
// the stability attributes are even enabled before using their queries.
|
||||||
if self.feat.staged_api || self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked {
|
if self.feat.staged_api() || self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked {
|
||||||
if let Some(stab) = self.tcx.lookup_stability(def_id) {
|
if let Some(stab) = self.tcx.lookup_stability(def_id) {
|
||||||
record!(self.tables.lookup_stability[def_id] <- stab)
|
record!(self.tables.lookup_stability[def_id] <- stab)
|
||||||
}
|
}
|
||||||
@ -1776,7 +1776,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||||||
fn encode_const_stability(&mut self, def_id: DefId) {
|
fn encode_const_stability(&mut self, def_id: DefId) {
|
||||||
// The query lookup can take a measurable amount of time in crates with many items. Check if
|
// The query lookup can take a measurable amount of time in crates with many items. Check if
|
||||||
// the stability attributes are even enabled before using their queries.
|
// the stability attributes are even enabled before using their queries.
|
||||||
if self.feat.staged_api || self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked {
|
if self.feat.staged_api() || self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked {
|
||||||
if let Some(stab) = self.tcx.lookup_const_stability(def_id) {
|
if let Some(stab) = self.tcx.lookup_const_stability(def_id) {
|
||||||
record!(self.tables.lookup_const_stability[def_id] <- stab)
|
record!(self.tables.lookup_const_stability[def_id] <- stab)
|
||||||
}
|
}
|
||||||
@ -1787,7 +1787,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
|||||||
fn encode_default_body_stability(&mut self, def_id: DefId) {
|
fn encode_default_body_stability(&mut self, def_id: DefId) {
|
||||||
// The query lookup can take a measurable amount of time in crates with many items. Check if
|
// The query lookup can take a measurable amount of time in crates with many items. Check if
|
||||||
// the stability attributes are even enabled before using their queries.
|
// the stability attributes are even enabled before using their queries.
|
||||||
if self.feat.staged_api || self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked {
|
if self.feat.staged_api() || self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked {
|
||||||
if let Some(stab) = self.tcx.lookup_default_body_stability(def_id) {
|
if let Some(stab) = self.tcx.lookup_default_body_stability(def_id) {
|
||||||
record!(self.tables.lookup_default_body_stability[def_id] <- stab)
|
record!(self.tables.lookup_default_body_stability[def_id] <- stab)
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
// @lcnr believes that successfully evaluating even though there are
|
// @lcnr believes that successfully evaluating even though there are
|
||||||
// used generic parameters is a bug of evaluation, so checking for it
|
// used generic parameters is a bug of evaluation, so checking for it
|
||||||
// here does feel somewhat sensible.
|
// here does feel somewhat sensible.
|
||||||
if !self.features().generic_const_exprs && ct.args.has_non_region_param() {
|
if !self.features().generic_const_exprs() && ct.args.has_non_region_param() {
|
||||||
let def_kind = self.def_kind(instance.def_id());
|
let def_kind = self.def_kind(instance.def_id());
|
||||||
assert!(
|
assert!(
|
||||||
matches!(
|
matches!(
|
||||||
|
@ -61,7 +61,7 @@ pub enum OverlapMode {
|
|||||||
|
|
||||||
impl OverlapMode {
|
impl OverlapMode {
|
||||||
pub fn get(tcx: TyCtxt<'_>, trait_id: DefId) -> OverlapMode {
|
pub fn get(tcx: TyCtxt<'_>, trait_id: DefId) -> OverlapMode {
|
||||||
let with_negative_coherence = tcx.features().with_negative_coherence;
|
let with_negative_coherence = tcx.features().with_negative_coherence();
|
||||||
let strict_coherence = tcx.has_attr(trait_id, sym::rustc_strict_coherence);
|
let strict_coherence = tcx.has_attr(trait_id, sym::rustc_strict_coherence);
|
||||||
|
|
||||||
if with_negative_coherence {
|
if with_negative_coherence {
|
||||||
|
@ -710,15 +710,15 @@ impl<'tcx> rustc_type_ir::inherent::Safety<TyCtxt<'tcx>> for hir::Safety {
|
|||||||
|
|
||||||
impl<'tcx> rustc_type_ir::inherent::Features<TyCtxt<'tcx>> for &'tcx rustc_feature::Features {
|
impl<'tcx> rustc_type_ir::inherent::Features<TyCtxt<'tcx>> for &'tcx rustc_feature::Features {
|
||||||
fn generic_const_exprs(self) -> bool {
|
fn generic_const_exprs(self) -> bool {
|
||||||
self.generic_const_exprs
|
self.generic_const_exprs()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn coroutine_clone(self) -> bool {
|
fn coroutine_clone(self) -> bool {
|
||||||
self.coroutine_clone
|
self.coroutine_clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn associated_const_equality(self) -> bool {
|
fn associated_const_equality(self) -> bool {
|
||||||
self.associated_const_equality
|
self.associated_const_equality()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,7 +398,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Array(inner, len) if tcx.features().transmute_generic_consts => {
|
ty::Array(inner, len) if tcx.features().transmute_generic_consts() => {
|
||||||
let len_eval = len.try_to_target_usize(tcx);
|
let len_eval = len.try_to_target_usize(tcx);
|
||||||
if len_eval == Some(0) {
|
if len_eval == Some(0) {
|
||||||
return Ok(SizeSkeleton::Known(Size::from_bytes(0), None));
|
return Ok(SizeSkeleton::Known(Size::from_bytes(0), None));
|
||||||
|
@ -1208,7 +1208,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.tcx().features().return_type_notation
|
if self.tcx().features().return_type_notation()
|
||||||
&& let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) =
|
&& let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) =
|
||||||
self.tcx().opt_rpitit_info(def_id)
|
self.tcx().opt_rpitit_info(def_id)
|
||||||
&& let ty::Alias(_, alias_ty) =
|
&& let ty::Alias(_, alias_ty) =
|
||||||
|
@ -750,7 +750,7 @@ impl<'tcx> Ty<'tcx> {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_diverging_default(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
pub fn new_diverging_default(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
|
||||||
if tcx.features().never_type_fallback { tcx.types.never } else { tcx.types.unit }
|
if tcx.features().never_type_fallback() { tcx.types.never } else { tcx.types.unit }
|
||||||
}
|
}
|
||||||
|
|
||||||
// lang and diagnostic tys
|
// lang and diagnostic tys
|
||||||
|
@ -877,8 +877,8 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
// FIXME(effects): This is suspicious and should probably not be done,
|
// FIXME(effects): This is suspicious and should probably not be done,
|
||||||
// especially now that we enforce host effects and then properly handle
|
// especially now that we enforce host effects and then properly handle
|
||||||
// effect vars during fallback.
|
// effect vars during fallback.
|
||||||
let mut host_always_on =
|
let mut host_always_on = !self.features().effects()
|
||||||
!self.features().effects || self.sess.opts.unstable_opts.unleash_the_miri_inside_of_you;
|
|| self.sess.opts.unstable_opts.unleash_the_miri_inside_of_you;
|
||||||
|
|
||||||
// Compute the constness required by the context.
|
// Compute the constness required by the context.
|
||||||
let const_context = self.hir().body_const_context(def_id);
|
let const_context = self.hir().body_const_context(def_id);
|
||||||
@ -1826,8 +1826,8 @@ pub fn is_doc_notable_trait(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
|||||||
/// cause an ICE that we otherwise may want to prevent.
|
/// cause an ICE that we otherwise may want to prevent.
|
||||||
pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::IntrinsicDef> {
|
pub fn intrinsic_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::IntrinsicDef> {
|
||||||
if (matches!(tcx.fn_sig(def_id).skip_binder().abi(), Abi::RustIntrinsic)
|
if (matches!(tcx.fn_sig(def_id).skip_binder().abi(), Abi::RustIntrinsic)
|
||||||
&& tcx.features().intrinsics)
|
&& tcx.features().intrinsics())
|
||||||
|| (tcx.has_attr(def_id, sym::rustc_intrinsic) && tcx.features().rustc_attrs)
|
|| (tcx.has_attr(def_id, sym::rustc_intrinsic) && tcx.features().rustc_attrs())
|
||||||
{
|
{
|
||||||
Some(ty::IntrinsicDef {
|
Some(ty::IntrinsicDef {
|
||||||
name: tcx.item_name(def_id.into()),
|
name: tcx.item_name(def_id.into()),
|
||||||
|
@ -163,7 +163,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
|
|
||||||
let tcx = this.tcx;
|
let tcx = this.tcx;
|
||||||
|
|
||||||
if tcx.features().unsized_fn_params {
|
if tcx.features().unsized_fn_params() {
|
||||||
let ty = expr.ty;
|
let ty = expr.ty;
|
||||||
let param_env = this.param_env;
|
let param_env = this.param_env;
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||||||
if let ty::Adt(def, _) = ty.kind()
|
if let ty::Adt(def, _) = ty.kind()
|
||||||
&& tcx.is_lang_item(def.did(), LangItem::String)
|
&& tcx.is_lang_item(def.did(), LangItem::String)
|
||||||
{
|
{
|
||||||
if !tcx.features().string_deref_patterns {
|
if !tcx.features().string_deref_patterns() {
|
||||||
span_bug!(
|
span_bug!(
|
||||||
test.span,
|
test.span,
|
||||||
"matching on `String` went through without enabling string_deref_patterns"
|
"matching on `String` went through without enabling string_deref_patterns"
|
||||||
|
@ -777,7 +777,7 @@ impl<'tcx> Cx<'tcx> {
|
|||||||
if_then_scope: region::Scope {
|
if_then_scope: region::Scope {
|
||||||
id: then.hir_id.local_id,
|
id: then.hir_id.local_id,
|
||||||
data: {
|
data: {
|
||||||
if expr.span.at_least_rust_2024() && tcx.features().if_let_rescope {
|
if expr.span.at_least_rust_2024() && tcx.features().if_let_rescope() {
|
||||||
region::ScopeData::IfThenRescope
|
region::ScopeData::IfThenRescope
|
||||||
} else {
|
} else {
|
||||||
region::ScopeData::IfThen
|
region::ScopeData::IfThen
|
||||||
|
@ -1126,7 +1126,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
|
|||||||
.map(|witness| cx.print_witness_pat(witness))
|
.map(|witness| cx.print_witness_pat(witness))
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(" | ");
|
.join(" | ");
|
||||||
if witnesses.iter().all(|p| p.is_never_pattern()) && cx.tcx.features().never_patterns {
|
if witnesses.iter().all(|p| p.is_never_pattern()) && cx.tcx.features().never_patterns() {
|
||||||
// Arms with a never pattern don't take a body.
|
// Arms with a never pattern don't take a body.
|
||||||
pattern
|
pattern
|
||||||
} else {
|
} else {
|
||||||
|
@ -1497,7 +1497,7 @@ fn check_field_tys_sized<'tcx>(
|
|||||||
) {
|
) {
|
||||||
// No need to check if unsized_locals/unsized_fn_params is disabled,
|
// No need to check if unsized_locals/unsized_fn_params is disabled,
|
||||||
// since we will error during typeck.
|
// since we will error during typeck.
|
||||||
if !tcx.features().unsized_locals && !tcx.features().unsized_fn_params {
|
if !tcx.features().unsized_locals() && !tcx.features().unsized_fn_params() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,7 +288,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||||||
values: FxIndexSet::with_capacity_and_hasher(num_values, Default::default()),
|
values: FxIndexSet::with_capacity_and_hasher(num_values, Default::default()),
|
||||||
evaluated: IndexVec::with_capacity(num_values),
|
evaluated: IndexVec::with_capacity(num_values),
|
||||||
next_opaque: Some(1),
|
next_opaque: Some(1),
|
||||||
feature_unsized_locals: tcx.features().unsized_locals,
|
feature_unsized_locals: tcx.features().unsized_locals(),
|
||||||
ssa,
|
ssa,
|
||||||
dominators,
|
dominators,
|
||||||
reused_locals: BitSet::new_empty(local_decls.len()),
|
reused_locals: BitSet::new_empty(local_decls.len()),
|
||||||
|
@ -12,7 +12,7 @@ use super::layout_test::ensure_wf;
|
|||||||
use crate::errors::{AbiInvalidAttribute, AbiNe, AbiOf, UnrecognizedField};
|
use crate::errors::{AbiInvalidAttribute, AbiNe, AbiOf, UnrecognizedField};
|
||||||
|
|
||||||
pub fn test_abi(tcx: TyCtxt<'_>) {
|
pub fn test_abi(tcx: TyCtxt<'_>) {
|
||||||
if !tcx.features().rustc_attrs {
|
if !tcx.features().rustc_attrs() {
|
||||||
// if the `rustc_attrs` feature is not enabled, don't bother testing ABI
|
// if the `rustc_attrs` feature is not enabled, don't bother testing ABI
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1187,7 +1187,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||||||
|
|
||||||
sym::rust_logo => {
|
sym::rust_logo => {
|
||||||
if self.check_attr_crate_level(attr, meta, hir_id)
|
if self.check_attr_crate_level(attr, meta, hir_id)
|
||||||
&& !self.tcx.features().rustdoc_internals
|
&& !self.tcx.features().rustdoc_internals()
|
||||||
{
|
{
|
||||||
feature_err(
|
feature_err(
|
||||||
&self.tcx.sess,
|
&self.tcx.sess,
|
||||||
@ -1774,7 +1774,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||||||
}
|
}
|
||||||
sym::align => {
|
sym::align => {
|
||||||
if let (Target::Fn | Target::Method(MethodKind::Inherent), false) =
|
if let (Target::Fn | Target::Method(MethodKind::Inherent), false) =
|
||||||
(target, self.tcx.features().fn_align)
|
(target, self.tcx.features().fn_align())
|
||||||
{
|
{
|
||||||
feature_err(
|
feature_err(
|
||||||
&self.tcx.sess,
|
&self.tcx.sess,
|
||||||
|
@ -105,7 +105,7 @@ impl<'tcx> CheckConstVisitor<'tcx> {
|
|||||||
|
|
||||||
// If this crate is not using stability attributes, or this function is not claiming to be a
|
// If this crate is not using stability attributes, or this function is not claiming to be a
|
||||||
// stable `const fn`, that is all that is required.
|
// stable `const fn`, that is all that is required.
|
||||||
if !tcx.features().staged_api || tcx.has_attr(def_id, sym::rustc_const_unstable) {
|
if !tcx.features().staged_api() || tcx.has_attr(def_id, sym::rustc_const_unstable) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ use crate::errors::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn test_layout(tcx: TyCtxt<'_>) {
|
pub fn test_layout(tcx: TyCtxt<'_>) {
|
||||||
if !tcx.features().rustc_attrs {
|
if !tcx.features().rustc_attrs() {
|
||||||
// if the `rustc_attrs` feature is not enabled, don't bother testing layout
|
// if the `rustc_attrs` feature is not enabled, don't bother testing layout
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ impl<'tcx> Visitor<'tcx> for LibFeatureCollector<'tcx> {
|
|||||||
fn lib_features(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> LibFeatures {
|
fn lib_features(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> LibFeatures {
|
||||||
// If `staged_api` is not enabled then we aren't allowed to define lib
|
// If `staged_api` is not enabled then we aren't allowed to define lib
|
||||||
// features; there is no point collecting them.
|
// features; there is no point collecting them.
|
||||||
if !tcx.features().staged_api {
|
if !tcx.features().staged_api() {
|
||||||
return LibFeatures::default();
|
return LibFeatures::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.tcx.features().staged_api {
|
if !self.tcx.features().staged_api() {
|
||||||
// Propagate unstability. This can happen even for non-staged-api crates in case
|
// Propagate unstability. This can happen even for non-staged-api crates in case
|
||||||
// -Zforce-unstable-if-unmarked is set.
|
// -Zforce-unstable-if-unmarked is set.
|
||||||
if let Some(stab) = self.parent_stab {
|
if let Some(stab) = self.parent_stab {
|
||||||
@ -541,7 +541,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_missing_const_stability(&self, def_id: LocalDefId, span: Span) {
|
fn check_missing_const_stability(&self, def_id: LocalDefId, span: Span) {
|
||||||
if !self.tcx.features().staged_api {
|
if !self.tcx.features().staged_api() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -734,7 +734,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
|
|||||||
// items.
|
// items.
|
||||||
hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref t), self_ty, items, .. }) => {
|
hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref t), self_ty, items, .. }) => {
|
||||||
let features = self.tcx.features();
|
let features = self.tcx.features();
|
||||||
if features.staged_api {
|
if features.staged_api() {
|
||||||
let attrs = self.tcx.hir().attrs(item.hir_id());
|
let attrs = self.tcx.hir().attrs(item.hir_id());
|
||||||
let stab = attr::find_stability(self.tcx.sess, attrs, item.span);
|
let stab = attr::find_stability(self.tcx.sess, attrs, item.span);
|
||||||
let const_stab = attr::find_const_stability(self.tcx.sess, attrs, item.span);
|
let const_stab = attr::find_const_stability(self.tcx.sess, attrs, item.span);
|
||||||
@ -762,7 +762,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
|
|||||||
|
|
||||||
// `#![feature(const_trait_impl)]` is unstable, so any impl declared stable
|
// `#![feature(const_trait_impl)]` is unstable, so any impl declared stable
|
||||||
// needs to have an error emitted.
|
// needs to have an error emitted.
|
||||||
if features.const_trait_impl
|
if features.const_trait_impl()
|
||||||
&& self.tcx.is_const_trait_impl_raw(item.owner_id.to_def_id())
|
&& self.tcx.is_const_trait_impl_raw(item.owner_id.to_def_id())
|
||||||
&& const_stab.is_some_and(|(stab, _)| stab.is_const_stable())
|
&& const_stab.is_some_and(|(stab, _)| stab.is_const_stable())
|
||||||
{
|
{
|
||||||
@ -926,7 +926,7 @@ impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> {
|
|||||||
/// libraries, identify activated features that don't exist and error about them.
|
/// libraries, identify activated features that don't exist and error about them.
|
||||||
pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
|
pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
|
||||||
let is_staged_api =
|
let is_staged_api =
|
||||||
tcx.sess.opts.unstable_opts.force_unstable_if_unmarked || tcx.features().staged_api;
|
tcx.sess.opts.unstable_opts.force_unstable_if_unmarked || tcx.features().staged_api();
|
||||||
if is_staged_api {
|
if is_staged_api {
|
||||||
let effective_visibilities = &tcx.effective_visibilities(());
|
let effective_visibilities = &tcx.effective_visibilities(());
|
||||||
let mut missing = MissingStabilityAnnotations { tcx, effective_visibilities };
|
let mut missing = MissingStabilityAnnotations { tcx, effective_visibilities };
|
||||||
|
@ -891,7 +891,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
|
|||||||
print::write_slice_like(&mut s, &prefix, has_dot_dot, &suffix).unwrap();
|
print::write_slice_like(&mut s, &prefix, has_dot_dot, &suffix).unwrap();
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
Never if self.tcx.features().never_patterns => "!".to_string(),
|
Never if self.tcx.features().never_patterns() => "!".to_string(),
|
||||||
Never | Wildcard | NonExhaustive | Hidden | PrivateUninhabited => "_".to_string(),
|
Never | Wildcard | NonExhaustive | Hidden | PrivateUninhabited => "_".to_string(),
|
||||||
Missing { .. } => bug!(
|
Missing { .. } => bug!(
|
||||||
"trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
|
"trying to convert a `Missing` constructor into a `Pat`; this is probably a bug,
|
||||||
@ -915,7 +915,7 @@ fn would_print_as_wildcard(tcx: TyCtxt<'_>, p: &WitnessPat<'_, '_>) -> bool {
|
|||||||
| Constructor::NonExhaustive
|
| Constructor::NonExhaustive
|
||||||
| Constructor::Hidden
|
| Constructor::Hidden
|
||||||
| Constructor::PrivateUninhabited => true,
|
| Constructor::PrivateUninhabited => true,
|
||||||
Constructor::Never if !tcx.features().never_patterns => true,
|
Constructor::Never if !tcx.features().never_patterns() => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -929,7 +929,7 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
|
|||||||
type PatData = &'p Pat<'tcx>;
|
type PatData = &'p Pat<'tcx>;
|
||||||
|
|
||||||
fn is_exhaustive_patterns_feature_on(&self) -> bool {
|
fn is_exhaustive_patterns_feature_on(&self) -> bool {
|
||||||
self.tcx.features().exhaustive_patterns
|
self.tcx.features().exhaustive_patterns()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ctor_arity(&self, ctor: &crate::constructor::Constructor<Self>, ty: &Self::Ty) -> usize {
|
fn ctor_arity(&self, ctor: &crate::constructor::Constructor<Self>, ty: &Self::Ty) -> usize {
|
||||||
|
@ -115,7 +115,7 @@ impl<'tcx> HashStable<StableHashingContext<'tcx>> for rustc_feature::Features {
|
|||||||
self.enabled_lang_features().hash_stable(hcx, hasher);
|
self.enabled_lang_features().hash_stable(hcx, hasher);
|
||||||
self.enabled_lib_features().hash_stable(hcx, hasher);
|
self.enabled_lib_features().hash_stable(hcx, hasher);
|
||||||
|
|
||||||
self.all_lang_features()[..].hash_stable(hcx, hasher);
|
// FIXME: why do we hash something that is a compile-time constant?
|
||||||
for feature in rustc_feature::UNSTABLE_FEATURES.iter() {
|
for feature in rustc_feature::UNSTABLE_FEATURES.iter() {
|
||||||
feature.feature.name.hash_stable(hcx, hasher);
|
feature.feature.name.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
|
@ -606,7 +606,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
Scope::BuiltinTypes => match this.builtin_types_bindings.get(&ident.name) {
|
Scope::BuiltinTypes => match this.builtin_types_bindings.get(&ident.name) {
|
||||||
Some(binding) => {
|
Some(binding) => {
|
||||||
if matches!(ident.name, sym::f16)
|
if matches!(ident.name, sym::f16)
|
||||||
&& !this.tcx.features().f16
|
&& !this.tcx.features().f16()
|
||||||
&& !ident.span.allows_unstable(sym::f16)
|
&& !ident.span.allows_unstable(sym::f16)
|
||||||
&& finalize.is_some()
|
&& finalize.is_some()
|
||||||
&& innermost_result.is_none()
|
&& innermost_result.is_none()
|
||||||
@ -620,7 +620,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
if matches!(ident.name, sym::f128)
|
if matches!(ident.name, sym::f128)
|
||||||
&& !this.tcx.features().f128
|
&& !this.tcx.features().f128()
|
||||||
&& !ident.span.allows_unstable(sym::f128)
|
&& !ident.span.allows_unstable(sym::f128)
|
||||||
&& finalize.is_some()
|
&& finalize.is_some()
|
||||||
&& innermost_result.is_none()
|
&& innermost_result.is_none()
|
||||||
|
@ -2683,7 +2683,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||||||
self.with_generic_param_rib(
|
self.with_generic_param_rib(
|
||||||
&generics.params,
|
&generics.params,
|
||||||
RibKind::Item(
|
RibKind::Item(
|
||||||
if self.r.tcx.features().generic_const_items {
|
if self.r.tcx.features().generic_const_items() {
|
||||||
HasGenericParams::Yes(generics.span)
|
HasGenericParams::Yes(generics.span)
|
||||||
} else {
|
} else {
|
||||||
HasGenericParams::No
|
HasGenericParams::No
|
||||||
@ -2888,7 +2888,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||||||
RibKind::Normal => {
|
RibKind::Normal => {
|
||||||
// FIXME(non_lifetime_binders): Stop special-casing
|
// FIXME(non_lifetime_binders): Stop special-casing
|
||||||
// const params to error out here.
|
// const params to error out here.
|
||||||
if self.r.tcx.features().non_lifetime_binders
|
if self.r.tcx.features().non_lifetime_binders()
|
||||||
&& matches!(param.kind, GenericParamKind::Type { .. })
|
&& matches!(param.kind, GenericParamKind::Type { .. })
|
||||||
{
|
{
|
||||||
Res::Def(def_kind, def_id.to_def_id())
|
Res::Def(def_kind, def_id.to_def_id())
|
||||||
@ -4411,10 +4411,10 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||||||
let tcx = self.r.tcx();
|
let tcx = self.r.tcx();
|
||||||
|
|
||||||
let gate_err_sym_msg = match prim {
|
let gate_err_sym_msg = match prim {
|
||||||
PrimTy::Float(FloatTy::F16) if !tcx.features().f16 => {
|
PrimTy::Float(FloatTy::F16) if !tcx.features().f16() => {
|
||||||
Some((sym::f16, "the type `f16` is unstable"))
|
Some((sym::f16, "the type `f16` is unstable"))
|
||||||
}
|
}
|
||||||
PrimTy::Float(FloatTy::F128) if !tcx.features().f128 => {
|
PrimTy::Float(FloatTy::F128) if !tcx.features().f128() => {
|
||||||
Some((sym::f128, "the type `f128` is unstable"))
|
Some((sym::f128, "the type `f128` is unstable"))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -4565,7 +4565,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
AnonConstKind::InlineConst => ConstantHasGenerics::Yes,
|
AnonConstKind::InlineConst => ConstantHasGenerics::Yes,
|
||||||
AnonConstKind::ConstArg(_) => {
|
AnonConstKind::ConstArg(_) => {
|
||||||
if self.r.tcx.features().generic_const_exprs || is_trivial_const_arg {
|
if self.r.tcx.features().generic_const_exprs() || is_trivial_const_arg {
|
||||||
ConstantHasGenerics::Yes
|
ConstantHasGenerics::Yes
|
||||||
} else {
|
} else {
|
||||||
ConstantHasGenerics::No(NoConstantGenericsReason::NonTrivialConstArg)
|
ConstantHasGenerics::No(NoConstantGenericsReason::NonTrivialConstArg)
|
||||||
|
@ -1198,7 +1198,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||||||
// const generics. Of course, `Struct` and `Enum` may contain ty params, too, but the
|
// const generics. Of course, `Struct` and `Enum` may contain ty params, too, but the
|
||||||
// benefits of including them here outweighs the small number of false positives.
|
// benefits of including them here outweighs the small number of false positives.
|
||||||
Some(Res::Def(DefKind::Struct | DefKind::Enum, _))
|
Some(Res::Def(DefKind::Struct | DefKind::Enum, _))
|
||||||
if self.r.tcx.features().adt_const_params =>
|
if self.r.tcx.features().adt_const_params() =>
|
||||||
{
|
{
|
||||||
Applicability::MaybeIncorrect
|
Applicability::MaybeIncorrect
|
||||||
}
|
}
|
||||||
@ -2773,7 +2773,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||||||
// Avoid suggesting placing lifetime parameters on constant items unless the relevant
|
// Avoid suggesting placing lifetime parameters on constant items unless the relevant
|
||||||
// feature is enabled. Suggest the parent item as a possible location if applicable.
|
// feature is enabled. Suggest the parent item as a possible location if applicable.
|
||||||
if let LifetimeBinderKind::ConstItem = kind
|
if let LifetimeBinderKind::ConstItem = kind
|
||||||
&& !self.r.tcx().features().generic_const_items
|
&& !self.r.tcx().features().generic_const_items()
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -2934,7 +2934,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
NoConstantGenericsReason::NonTrivialConstArg => {
|
NoConstantGenericsReason::NonTrivialConstArg => {
|
||||||
assert!(!self.r.tcx.features().generic_const_exprs);
|
assert!(!self.r.tcx.features().generic_const_exprs());
|
||||||
self.r
|
self.r
|
||||||
.dcx()
|
.dcx()
|
||||||
.create_err(errors::ParamInNonTrivialAnonConst {
|
.create_err(errors::ParamInNonTrivialAnonConst {
|
||||||
|
@ -661,7 +661,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We are trying to avoid reporting this error if other related errors were reported.
|
// We are trying to avoid reporting this error if other related errors were reported.
|
||||||
if res != Res::Err && inner_attr && !self.tcx.features().custom_inner_attributes {
|
if res != Res::Err && inner_attr && !self.tcx.features().custom_inner_attributes() {
|
||||||
let is_macro = match res {
|
let is_macro = match res {
|
||||||
Res::Def(..) => true,
|
Res::Def(..) => true,
|
||||||
Res::NonMacroAttr(..) => false,
|
Res::NonMacroAttr(..) => false,
|
||||||
@ -690,7 +690,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
&& namespace.ident.name == sym::diagnostic
|
&& namespace.ident.name == sym::diagnostic
|
||||||
&& !(attribute.ident.name == sym::on_unimplemented
|
&& !(attribute.ident.name == sym::on_unimplemented
|
||||||
|| (attribute.ident.name == sym::do_not_recommend
|
|| (attribute.ident.name == sym::do_not_recommend
|
||||||
&& self.tcx.features().do_not_recommend))
|
&& self.tcx.features().do_not_recommend()))
|
||||||
{
|
{
|
||||||
let distance =
|
let distance =
|
||||||
edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5);
|
edit_distance(attribute.ident.name.as_str(), sym::on_unimplemented.as_str(), 5);
|
||||||
|
@ -18,7 +18,7 @@ pub fn report_symbol_names(tcx: TyCtxt<'_>) {
|
|||||||
// if the `rustc_attrs` feature is not enabled, then the
|
// if the `rustc_attrs` feature is not enabled, then the
|
||||||
// attributes we are interested in cannot be present anyway, so
|
// attributes we are interested in cannot be present anyway, so
|
||||||
// skip the walk.
|
// skip the walk.
|
||||||
if !tcx.features().rustc_attrs {
|
if !tcx.features().rustc_attrs() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3026,7 +3026,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||||||
obligation: &PredicateObligation<'tcx>,
|
obligation: &PredicateObligation<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<Diag<'a>, ErrorGuaranteed> {
|
) -> Result<Diag<'a>, ErrorGuaranteed> {
|
||||||
if !self.tcx.features().generic_const_exprs {
|
if !self.tcx.features().generic_const_exprs() {
|
||||||
let guar = self
|
let guar = self
|
||||||
.dcx()
|
.dcx()
|
||||||
.struct_span_err(span, "constant expression depends on a generic parameter")
|
.struct_span_err(span, "constant expression depends on a generic parameter")
|
||||||
|
@ -3044,7 +3044,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||||||
if local {
|
if local {
|
||||||
err.note("all local variables must have a statically known size");
|
err.note("all local variables must have a statically known size");
|
||||||
}
|
}
|
||||||
if !tcx.features().unsized_locals {
|
if !tcx.features().unsized_locals() {
|
||||||
err.help("unsized locals are gated as an unstable feature");
|
err.help("unsized locals are gated as an unstable feature");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3125,7 +3125,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||||||
err.note("all function arguments must have a statically known size");
|
err.note("all function arguments must have a statically known size");
|
||||||
}
|
}
|
||||||
if tcx.sess.opts.unstable_features.is_nightly_build()
|
if tcx.sess.opts.unstable_features.is_nightly_build()
|
||||||
&& !tcx.features().unsized_fn_params
|
&& !tcx.features().unsized_fn_params()
|
||||||
{
|
{
|
||||||
err.help("unsized fn params are gated as an unstable feature");
|
err.help("unsized fn params are gated as an unstable feature");
|
||||||
}
|
}
|
||||||
@ -4510,7 +4510,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||||
) {
|
) {
|
||||||
// Don't suggest if RTN is active -- we should prefer a where-clause bound instead.
|
// Don't suggest if RTN is active -- we should prefer a where-clause bound instead.
|
||||||
if self.tcx.features().return_type_notation {
|
if self.tcx.features().return_type_notation() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ pub fn is_const_evaluatable<'tcx>(
|
|||||||
ty::ConstKind::Infer(_) => return Err(NotConstEvaluatable::MentionsInfer),
|
ty::ConstKind::Infer(_) => return Err(NotConstEvaluatable::MentionsInfer),
|
||||||
};
|
};
|
||||||
|
|
||||||
if tcx.features().generic_const_exprs {
|
if tcx.features().generic_const_exprs() {
|
||||||
let ct = tcx.expand_abstract_consts(unexpanded_ct);
|
let ct = tcx.expand_abstract_consts(unexpanded_ct);
|
||||||
|
|
||||||
let is_anon_ct = if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
|
let is_anon_ct = if let ty::ConstKind::Unevaluated(uv) = ct.kind() {
|
||||||
|
@ -254,7 +254,7 @@ fn super_predicates_have_non_lifetime_binders(
|
|||||||
trait_def_id: DefId,
|
trait_def_id: DefId,
|
||||||
) -> SmallVec<[Span; 1]> {
|
) -> SmallVec<[Span; 1]> {
|
||||||
// If non_lifetime_binders is disabled, then exit early
|
// If non_lifetime_binders is disabled, then exit early
|
||||||
if !tcx.features().non_lifetime_binders {
|
if !tcx.features().non_lifetime_binders() {
|
||||||
return SmallVec::new();
|
return SmallVec::new();
|
||||||
}
|
}
|
||||||
tcx.explicit_super_predicates_of(trait_def_id)
|
tcx.explicit_super_predicates_of(trait_def_id)
|
||||||
@ -327,7 +327,7 @@ pub fn dyn_compatibility_violations_for_assoc_item(
|
|||||||
.collect(),
|
.collect(),
|
||||||
// Associated types can only be dyn-compatible if they have `Self: Sized` bounds.
|
// Associated types can only be dyn-compatible if they have `Self: Sized` bounds.
|
||||||
ty::AssocKind::Type => {
|
ty::AssocKind::Type => {
|
||||||
if !tcx.features().generic_associated_types_extended
|
if !tcx.features().generic_associated_types_extended()
|
||||||
&& !tcx.generics_of(item.def_id).is_own_empty()
|
&& !tcx.generics_of(item.def_id).is_own_empty()
|
||||||
&& !item.is_impl_trait_in_trait()
|
&& !item.is_impl_trait_in_trait()
|
||||||
{
|
{
|
||||||
|
@ -598,7 +598,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
|
|||||||
ty::PredicateKind::ConstEquate(c1, c2) => {
|
ty::PredicateKind::ConstEquate(c1, c2) => {
|
||||||
let tcx = self.selcx.tcx();
|
let tcx = self.selcx.tcx();
|
||||||
assert!(
|
assert!(
|
||||||
tcx.features().generic_const_exprs,
|
tcx.features().generic_const_exprs(),
|
||||||
"`ConstEquate` without a feature gate: {c1:?} {c2:?}",
|
"`ConstEquate` without a feature gate: {c1:?} {c2:?}",
|
||||||
);
|
);
|
||||||
// FIXME: we probably should only try to unify abstract constants
|
// FIXME: we probably should only try to unify abstract constants
|
||||||
|
@ -346,7 +346,7 @@ pub fn normalize_param_env_or_error<'tcx>(
|
|||||||
let mut predicates: Vec<_> = util::elaborate(
|
let mut predicates: Vec<_> = util::elaborate(
|
||||||
tcx,
|
tcx,
|
||||||
unnormalized_env.caller_bounds().into_iter().map(|predicate| {
|
unnormalized_env.caller_bounds().into_iter().map(|predicate| {
|
||||||
if tcx.features().generic_const_exprs {
|
if tcx.features().generic_const_exprs() {
|
||||||
return predicate;
|
return predicate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,7 +402,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
|
|||||||
#[instrument(skip(self), level = "debug")]
|
#[instrument(skip(self), level = "debug")]
|
||||||
fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
fn fold_const(&mut self, constant: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
||||||
let tcx = self.selcx.tcx();
|
let tcx = self.selcx.tcx();
|
||||||
if tcx.features().generic_const_exprs
|
if tcx.features().generic_const_exprs()
|
||||||
|| !needs_normalization(&constant, self.param_env.reveal())
|
|| !needs_normalization(&constant, self.param_env.reveal())
|
||||||
{
|
{
|
||||||
constant
|
constant
|
||||||
|
@ -189,7 +189,7 @@ pub(super) fn poly_project_and_unify_term<'cx, 'tcx>(
|
|||||||
ProjectAndUnifyResult::MismatchedProjectionTypes(e) => Err(e),
|
ProjectAndUnifyResult::MismatchedProjectionTypes(e) => Err(e),
|
||||||
ProjectAndUnifyResult::Holds(obligations)
|
ProjectAndUnifyResult::Holds(obligations)
|
||||||
if old_universe != new_universe
|
if old_universe != new_universe
|
||||||
&& selcx.tcx().features().generic_associated_types_extended =>
|
&& selcx.tcx().features().generic_associated_types_extended() =>
|
||||||
{
|
{
|
||||||
// If the `generic_associated_types_extended` feature is active, then we ignore any
|
// If the `generic_associated_types_extended` feature is active, then we ignore any
|
||||||
// obligations references lifetimes from any universe greater than or equal to the
|
// obligations references lifetimes from any universe greater than or equal to the
|
||||||
|
@ -876,7 +876,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(principal) = data.principal() {
|
if let Some(principal) = data.principal() {
|
||||||
if !self.infcx.tcx.features().dyn_compatible_for_dispatch {
|
if !self.infcx.tcx.features().dyn_compatible_for_dispatch() {
|
||||||
principal.with_self_ty(self.tcx(), self_ty)
|
principal.with_self_ty(self.tcx(), self_ty)
|
||||||
} else if self.tcx().is_dyn_compatible(principal.def_id()) {
|
} else if self.tcx().is_dyn_compatible(principal.def_id()) {
|
||||||
principal.with_self_ty(self.tcx(), self_ty)
|
principal.with_self_ty(self.tcx(), self_ty)
|
||||||
@ -936,7 +936,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
if tcx.features().trait_upcasting {
|
if tcx.features().trait_upcasting() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,7 +402,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
|
|
||||||
let mut assume = predicate.trait_ref.args.const_at(2);
|
let mut assume = predicate.trait_ref.args.const_at(2);
|
||||||
// FIXME(min_generic_const_exprs): We should shallowly normalize this.
|
// FIXME(min_generic_const_exprs): We should shallowly normalize this.
|
||||||
if self.tcx().features().generic_const_exprs {
|
if self.tcx().features().generic_const_exprs() {
|
||||||
assume = assume.normalize_internal(self.tcx(), obligation.param_env);
|
assume = assume.normalize_internal(self.tcx(), obligation.param_env);
|
||||||
}
|
}
|
||||||
let Some(assume) =
|
let Some(assume) =
|
||||||
@ -626,7 +626,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
for assoc_type in assoc_types {
|
for assoc_type in assoc_types {
|
||||||
let defs: &ty::Generics = tcx.generics_of(assoc_type);
|
let defs: &ty::Generics = tcx.generics_of(assoc_type);
|
||||||
|
|
||||||
if !defs.own_params.is_empty() && !tcx.features().generic_associated_types_extended {
|
if !defs.own_params.is_empty() && !tcx.features().generic_associated_types_extended() {
|
||||||
tcx.dcx().span_delayed_bug(
|
tcx.dcx().span_delayed_bug(
|
||||||
obligation.cause.span,
|
obligation.cause.span,
|
||||||
"GATs in trait object shouldn't have been considered",
|
"GATs in trait object shouldn't have been considered",
|
||||||
|
@ -865,7 +865,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
ty::PredicateKind::ConstEquate(c1, c2) => {
|
ty::PredicateKind::ConstEquate(c1, c2) => {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
assert!(
|
assert!(
|
||||||
tcx.features().generic_const_exprs,
|
tcx.features().generic_const_exprs(),
|
||||||
"`ConstEquate` without a feature gate: {c1:?} {c2:?}",
|
"`ConstEquate` without a feature gate: {c1:?} {c2:?}",
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -2195,7 +2195,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||||||
match self.tcx().coroutine_movability(coroutine_def_id) {
|
match self.tcx().coroutine_movability(coroutine_def_id) {
|
||||||
hir::Movability::Static => None,
|
hir::Movability::Static => None,
|
||||||
hir::Movability::Movable => {
|
hir::Movability::Movable => {
|
||||||
if self.tcx().features().coroutine_clone {
|
if self.tcx().features().coroutine_clone() {
|
||||||
let resolved_upvars =
|
let resolved_upvars =
|
||||||
self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty());
|
self.infcx.shallow_resolve(args.as_coroutine().tupled_upvars_ty());
|
||||||
let resolved_witness =
|
let resolved_witness =
|
||||||
|
@ -136,7 +136,7 @@ pub fn translate_args_with_cause<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn specialization_enabled_in(tcx: TyCtxt<'_>, _: LocalCrate) -> bool {
|
pub(super) fn specialization_enabled_in(tcx: TyCtxt<'_>, _: LocalCrate) -> bool {
|
||||||
tcx.features().specialization || tcx.features().min_specialization
|
tcx.features().specialization() || tcx.features().min_specialization()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is `impl1` a specialization of `impl2`?
|
/// Is `impl1` a specialization of `impl2`?
|
||||||
|
@ -82,7 +82,7 @@ impl<'tcx> At<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(self.infcx.resolve_vars_if_possible(new_infer_ct))
|
Ok(self.infcx.resolve_vars_if_possible(new_infer_ct))
|
||||||
} else if self.infcx.tcx.features().generic_const_exprs {
|
} else if self.infcx.tcx.features().generic_const_exprs() {
|
||||||
Ok(ct.normalize_internal(self.infcx.tcx, self.param_env))
|
Ok(ct.normalize_internal(self.infcx.tcx, self.param_env))
|
||||||
} else {
|
} else {
|
||||||
Ok(self.normalize(ct).into_value_registering_obligations(self.infcx, fulfill_cx))
|
Ok(self.normalize(ct).into_value_registering_obligations(self.infcx, fulfill_cx))
|
||||||
|
@ -836,7 +836,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
|
|||||||
// obligations that don't refer to Self and
|
// obligations that don't refer to Self and
|
||||||
// checking those
|
// checking those
|
||||||
|
|
||||||
let defer_to_coercion = tcx.features().dyn_compatible_for_dispatch;
|
let defer_to_coercion = tcx.features().dyn_compatible_for_dispatch();
|
||||||
|
|
||||||
if !defer_to_coercion {
|
if !defer_to_coercion {
|
||||||
if let Some(principal) = data.principal_def_id() {
|
if let Some(principal) = data.principal_def_id() {
|
||||||
|
@ -181,7 +181,7 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A
|
|||||||
fn associated_type_for_effects(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
|
fn associated_type_for_effects(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
|
||||||
// don't synthesize the associated type even if the user has written `const_trait`
|
// don't synthesize the associated type even if the user has written `const_trait`
|
||||||
// if the effects feature is disabled.
|
// if the effects feature is disabled.
|
||||||
if !tcx.features().effects {
|
if !tcx.features().effects() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let (feed, parent_did) = match tcx.def_kind(def_id) {
|
let (feed, parent_did) = match tcx.def_kind(def_id) {
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user