Skip to content

Commit 6f2c6ef

Browse files
committed
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.
1 parent 94b72d6 commit 6f2c6ef

File tree

4 files changed

+63
-40
lines changed

4 files changed

+63
-40
lines changed

compiler/rustc_feature/src/builtin_attrs.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -597,9 +597,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
597597
),
598598

599599
rustc_attr!(
600-
rustc_never_type_mode, Normal, template!(NameValueStr: "fallback_to_unit|fallback_to_niko|fallback_to_never|no_fallback"), ErrorFollowing,
600+
rustc_never_type_options,
601+
Normal,
602+
template!(List: r#"/*opt*/ fallback = "unit|niko|never|no""#),
603+
ErrorFollowing,
601604
EncodeCrossCrate::No,
602-
"`rustc_never_type_fallback` is used to experiment with never type fallback and work on \
605+
"`rustc_never_type_options` is used to experiment with never type fallback and work on \
603606
never type stabilization, and will never be stable"
604607
),
605608

compiler/rustc_hir_typeck/src/fallback.rs

+4-32
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@ use rustc_data_structures::{
44
graph::{iterate::DepthFirstSearch, vec_graph::VecGraph},
55
unord::{UnordBag, UnordMap, UnordSet},
66
};
7-
use rustc_hir::def_id::CRATE_DEF_ID;
87
use rustc_infer::infer::{DefineOpaqueTypes, InferOk};
98
use rustc_middle::ty::{self, Ty};
10-
use rustc_span::sym;
119

12-
enum DivergingFallbackBehavior {
10+
#[derive(Copy, Clone)]
11+
pub enum DivergingFallbackBehavior {
1312
/// Always fallback to `()` (aka "always spontaneous decay")
1413
FallbackToUnit,
1514
/// Sometimes fallback to `!`, but mainly fallback to `()` so that most of the crates are not broken.
@@ -78,9 +77,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
7877
return false;
7978
}
8079

81-
let diverging_behavior = self.diverging_fallback_behavior();
82-
let diverging_fallback =
83-
self.calculate_diverging_fallback(&unresolved_variables, diverging_behavior);
80+
let diverging_fallback = self
81+
.calculate_diverging_fallback(&unresolved_variables, self.diverging_fallback_behavior);
8482

8583
// We do fallback in two passes, to try to generate
8684
// better error messages.
@@ -94,32 +92,6 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
9492
fallback_occurred
9593
}
9694

97-
fn diverging_fallback_behavior(&self) -> DivergingFallbackBehavior {
98-
let Some((mode, span)) = self
99-
.tcx
100-
.get_attr(CRATE_DEF_ID, sym::rustc_never_type_mode)
101-
.map(|attr| (attr.value_str().unwrap(), attr.span))
102-
else {
103-
if self.tcx.features().never_type_fallback {
104-
return DivergingFallbackBehavior::FallbackToNiko;
105-
}
106-
107-
return DivergingFallbackBehavior::FallbackToUnit;
108-
};
109-
110-
match mode {
111-
sym::fallback_to_unit => DivergingFallbackBehavior::FallbackToUnit,
112-
sym::fallback_to_niko => DivergingFallbackBehavior::FallbackToNiko,
113-
sym::fallback_to_never => DivergingFallbackBehavior::FallbackToNever,
114-
sym::no_fallback => DivergingFallbackBehavior::NoFallback,
115-
_ => {
116-
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`)"));
117-
118-
DivergingFallbackBehavior::FallbackToUnit
119-
}
120-
}
121-
}
122-
12395
fn fallback_effects(&self) -> bool {
12496
let unsolved_effects = self.unsolved_effects();
12597

compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs

+51-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ mod checks;
55
mod suggestions;
66

77
use crate::coercion::DynamicCoerceMany;
8+
use crate::fallback::DivergingFallbackBehavior;
89
use crate::{CoroutineTypes, Diverges, EnclosingBreakables, Inherited};
10+
use hir::def_id::CRATE_DEF_ID;
911
use rustc_errors::{DiagCtxt, ErrorGuaranteed};
1012
use rustc_hir as hir;
1113
use rustc_hir::def_id::{DefId, LocalDefId};
@@ -18,7 +20,7 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin
1820
use rustc_middle::ty::{self, Const, Ty, TyCtxt, TypeVisitableExt};
1921
use rustc_session::Session;
2022
use rustc_span::symbol::Ident;
21-
use rustc_span::{self, Span, DUMMY_SP};
23+
use rustc_span::{self, sym, Span, DUMMY_SP};
2224
use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
2325

2426
use std::cell::{Cell, RefCell};
@@ -108,6 +110,8 @@ pub struct FnCtxt<'a, 'tcx> {
108110
pub(super) inh: &'a Inherited<'tcx>,
109111

110112
pub(super) fallback_has_occurred: Cell<bool>,
113+
114+
pub(super) diverging_fallback_behavior: DivergingFallbackBehavior,
111115
}
112116

113117
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -116,6 +120,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
116120
param_env: ty::ParamEnv<'tcx>,
117121
body_id: LocalDefId,
118122
) -> FnCtxt<'a, 'tcx> {
123+
let diverging_fallback_behavior = parse_never_type_options_attr(inh.tcx);
119124
FnCtxt {
120125
body_id,
121126
param_env,
@@ -131,6 +136,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
131136
}),
132137
inh,
133138
fallback_has_occurred: Cell::new(false),
139+
diverging_fallback_behavior,
134140
}
135141
}
136142

@@ -374,3 +380,47 @@ impl<'tcx> LoweredTy<'tcx> {
374380
LoweredTy { raw, normalized }
375381
}
376382
}
383+
384+
fn parse_never_type_options_attr(tcx: TyCtxt<'_>) -> DivergingFallbackBehavior {
385+
use DivergingFallbackBehavior::*;
386+
387+
// Error handling is dubious here (unwraps), but that's probably fine for an internal attribute.
388+
// Just don't write incorrect attributes <3
389+
390+
let mut fallback = None;
391+
392+
let items = tcx
393+
.get_attr(CRATE_DEF_ID, sym::rustc_never_type_options)
394+
.map(|attr| attr.meta_item_list().unwrap())
395+
.unwrap_or_default();
396+
397+
for item in items {
398+
if item.has_name(sym::fallback) && fallback.is_none() {
399+
let mode = item.value_str().unwrap();
400+
match mode {
401+
sym::unit => fallback = Some(FallbackToUnit),
402+
sym::niko => fallback = Some(FallbackToNiko),
403+
sym::never => fallback = Some(FallbackToNever),
404+
sym::no => fallback = Some(NoFallback),
405+
_ => {
406+
tcx.dcx().span_err(item.span(), format!("unknown never type fallback mode: `{mode}` (supported: `unit`, `niko`, `never` and `no`)"));
407+
}
408+
};
409+
continue;
410+
}
411+
412+
tcx.dcx().span_err(
413+
item.span(),
414+
format!(
415+
"unknown never type option: `{}` (supported: `fallback`)",
416+
item.name_or_empty()
417+
),
418+
);
419+
}
420+
421+
let fallback = fallback.unwrap_or_else(|| {
422+
if tcx.features().never_type_fallback { FallbackToNiko } else { FallbackToUnit }
423+
});
424+
425+
fallback
426+
}

compiler/rustc_span/src/symbol.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -814,9 +814,7 @@ symbols! {
814814
fadd_algebraic,
815815
fadd_fast,
816816
fake_variadic,
817-
fallback_to_never,
818-
fallback_to_niko,
819-
fallback_to_unit,
817+
fallback,
820818
fdiv_algebraic,
821819
fdiv_fast,
822820
feature,
@@ -1227,6 +1225,7 @@ symbols! {
12271225
new_v1,
12281226
new_v1_formatted,
12291227
next,
1228+
niko,
12301229
nll,
12311230
no,
12321231
no_builtins,
@@ -1235,7 +1234,6 @@ symbols! {
12351234
no_crate_inject,
12361235
no_debug,
12371236
no_default_passes,
1238-
no_fallback,
12391237
no_implicit_prelude,
12401238
no_inline,
12411239
no_link,
@@ -1553,7 +1551,7 @@ symbols! {
15531551
rustc_mir,
15541552
rustc_must_implement_one_of,
15551553
rustc_never_returns_null_ptr,
1556-
rustc_never_type_mode,
1554+
rustc_never_type_options,
15571555
rustc_no_mir_inline,
15581556
rustc_nonnull_optimization_guaranteed,
15591557
rustc_nounwind,

0 commit comments

Comments
 (0)