about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMaybe Waffle <waffle.lapkin@gmail.com>2024-03-21 19:47:46 +0000
committerMaybe Waffle <waffle.lapkin@gmail.com>2024-03-21 19:47:46 +0000
commit6f2c6efe019ef57585e1099e701c800417037e04 (patch)
treed930c5676d5a7ecc976e097fb119aee242661b4c
parent94b72d6bebbddb5d17860914c4544f37365e988c (diff)
downloadrust-6f2c6efe019ef57585e1099e701c800417037e04.tar.gz
rust-6f2c6efe019ef57585e1099e701c800417037e04.zip
Change syntax of the never type attribute thingy
Previous:
  ```rust
  #![rustc_never_type_mode = "fallback_to_unit|..."]
  ```

New:
  ```rust
  #![rustc_never_type_options(fallback = "unit|...")]
  ```
This allows adding other options for other never-related experiments.
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/fallback.rs36
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs52
-rw-r--r--compiler/rustc_span/src/symbol.rs8
4 files changed, 63 insertions, 40 deletions
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index d4d7833cb21..22cf50fce7f 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -597,9 +597,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
 
     rustc_attr!(
-        rustc_never_type_mode, Normal, template!(NameValueStr: "fallback_to_unit|fallback_to_niko|fallback_to_never|no_fallback"), ErrorFollowing,
+        rustc_never_type_options,
+        Normal,
+        template!(List: r#"/*opt*/ fallback = "unit|niko|never|no""#),
+        ErrorFollowing,
         EncodeCrossCrate::No,
-        "`rustc_never_type_fallback` is used to experiment with never type fallback and work on \
+        "`rustc_never_type_options` is used to experiment with never type fallback and work on \
          never type stabilization, and will never be stable"
     ),
 
diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs
index c16e941d4c5..140618e97cc 100644
--- a/compiler/rustc_hir_typeck/src/fallback.rs
+++ b/compiler/rustc_hir_typeck/src/fallback.rs
@@ -4,12 +4,11 @@ use rustc_data_structures::{
     graph::{iterate::DepthFirstSearch, vec_graph::VecGraph},
     unord::{UnordBag, UnordMap, UnordSet},
 };
-use rustc_hir::def_id::CRATE_DEF_ID;
 use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
 use rustc_middle::ty::{self, Ty};
-use rustc_span::sym;
 
-enum DivergingFallbackBehavior {
+#[derive(Copy, Clone)]
+pub enum DivergingFallbackBehavior {
     /// Always fallback to `()` (aka "always spontaneous decay")
     FallbackToUnit,
     /// Sometimes fallback to `!`, but mainly fallback to `()` so that most of the crates are not broken.
@@ -78,9 +77,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
             return false;
         }
 
-        let diverging_behavior = self.diverging_fallback_behavior();
-        let diverging_fallback =
-            self.calculate_diverging_fallback(&unresolved_variables, diverging_behavior);
+        let diverging_fallback = self
+            .calculate_diverging_fallback(&unresolved_variables, self.diverging_fallback_behavior);
 
         // We do fallback in two passes, to try to generate
         // better error messages.
@@ -94,32 +92,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
         fallback_occurred
     }
 
-    fn diverging_fallback_behavior(&self) -> DivergingFallbackBehavior {
-        let Some((mode, span)) = self
-            .tcx
-            .get_attr(CRATE_DEF_ID, sym::rustc_never_type_mode)
-            .map(|attr| (attr.value_str().unwrap(), attr.span))
-        else {
-            if self.tcx.features().never_type_fallback {
-                return DivergingFallbackBehavior::FallbackToNiko;
-            }
-
-            return DivergingFallbackBehavior::FallbackToUnit;
-        };
-
-        match mode {
-            sym::fallback_to_unit => DivergingFallbackBehavior::FallbackToUnit,
-            sym::fallback_to_niko => DivergingFallbackBehavior::FallbackToNiko,
-            sym::fallback_to_never => DivergingFallbackBehavior::FallbackToNever,
-            sym::no_fallback => DivergingFallbackBehavior::NoFallback,
-            _ => {
-                self.tcx.dcx().span_err(span, format!("unknown never type mode: `{mode}` (supported: `fallback_to_unit`, `fallback_to_niko`, `fallback_to_never` and `no_fallback`)"));
-
-                DivergingFallbackBehavior::FallbackToUnit
-            }
-        }
-    }
-
     fn fallback_effects(&self) -> bool {
         let unsolved_effects = self.unsolved_effects();
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 685b1af931e..fa948451d70 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -5,7 +5,9 @@ mod checks;
 mod suggestions;
 
 use crate::coercion::DynamicCoerceMany;
+use crate::fallback::DivergingFallbackBehavior;
 use crate::{CoroutineTypes, Diverges, EnclosingBreakables, Inherited};
+use hir::def_id::CRATE_DEF_ID;
 use rustc_errors::{DiagCtxt, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -18,7 +20,7 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin
 use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
 use rustc_session::Session;
 use rustc_span::symbol::Ident;
-use rustc_span::{self, Span, DUMMY_SP};
+use rustc_span::{self, sym, Span, DUMMY_SP};
 use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
 
 use std::cell::{Cell, RefCell};
@@ -108,6 +110,8 @@ pub struct FnCtxt<'a, 'tcx> {
     pub(super) inh: &'a Inherited<'tcx>,
 
     pub(super) fallback_has_occurred: Cell<bool>,
+
+    pub(super) diverging_fallback_behavior: DivergingFallbackBehavior,
 }
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -116,6 +120,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         param_env: ty::ParamEnv<'tcx>,
         body_id: LocalDefId,
     ) -> FnCtxt<'a, 'tcx> {
+        let diverging_fallback_behavior = parse_never_type_options_attr(inh.tcx);
         FnCtxt {
             body_id,
             param_env,
@@ -131,6 +136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }),
             inh,
             fallback_has_occurred: Cell::new(false),
+            diverging_fallback_behavior,
         }
     }
 
@@ -374,3 +380,47 @@ impl<'tcx> LoweredTy<'tcx> {
         LoweredTy { raw, normalized }
     }
 }
+
+fn parse_never_type_options_attr(tcx: TyCtxt<'_>) -> DivergingFallbackBehavior {
+    use DivergingFallbackBehavior::*;
+
+    // Error handling is dubious here (unwraps), but that's probably fine for an internal attribute.
+    // Just don't write incorrect attributes <3
+
+    let mut fallback = None;
+
+    let items = tcx
+        .get_attr(CRATE_DEF_ID, sym::rustc_never_type_options)
+        .map(|attr| attr.meta_item_list().unwrap())
+        .unwrap_or_default();
+
+    for item in items {
+        if item.has_name(sym::fallback) && fallback.is_none() {
+            let mode = item.value_str().unwrap();
+            match mode {
+                sym::unit => fallback = Some(FallbackToUnit),
+                sym::niko => fallback = Some(FallbackToNiko),
+                sym::never => fallback = Some(FallbackToNever),
+                sym::no => fallback = Some(NoFallback),
+                _ => {
+                    tcx.dcx().span_err(item.span(), format!("unknown never type fallback mode: `{mode}` (supported: `unit`, `niko`, `never` and `no`)"));
+                }
+            };
+            continue;
+        }
+
+        tcx.dcx().span_err(
+            item.span(),
+            format!(
+                "unknown never type option: `{}` (supported: `fallback`)",
+                item.name_or_empty()
+            ),
+        );
+    }
+
+    let fallback = fallback.unwrap_or_else(|| {
+        if tcx.features().never_type_fallback { FallbackToNiko } else { FallbackToUnit }
+    });
+
+    fallback
+}
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 8b911a41a11..77170406c06 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -814,9 +814,7 @@ symbols! {
         fadd_algebraic,
         fadd_fast,
         fake_variadic,
-        fallback_to_never,
-        fallback_to_niko,
-        fallback_to_unit,
+        fallback,
         fdiv_algebraic,
         fdiv_fast,
         feature,
@@ -1227,6 +1225,7 @@ symbols! {
         new_v1,
         new_v1_formatted,
         next,
+        niko,
         nll,
         no,
         no_builtins,
@@ -1235,7 +1234,6 @@ symbols! {
         no_crate_inject,
         no_debug,
         no_default_passes,
-        no_fallback,
         no_implicit_prelude,
         no_inline,
         no_link,
@@ -1553,7 +1551,7 @@ symbols! {
         rustc_mir,
         rustc_must_implement_one_of,
         rustc_never_returns_null_ptr,
-        rustc_never_type_mode,
+        rustc_never_type_options,
         rustc_no_mir_inline,
         rustc_nonnull_optimization_guaranteed,
         rustc_nounwind,