Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
7e79dcd
Drive-by fix string fmt
estebank Mar 9, 2024
2d3435b
Detect calls to `.clone()` on `T: !Clone` types on borrowck errors
estebank Mar 9, 2024
b367c25
Tweak wording
estebank Mar 9, 2024
0953608
Account for UnOps in borrowck message
estebank Mar 12, 2024
8da2621
print ghosts
Manishearth Mar 14, 2024
343c77c
Refactor visibility_print_with_space to directly take an item
Manishearth Mar 14, 2024
1020156
print doc(hidden)
Manishearth Mar 14, 2024
bd03fad
Make compact
Manishearth Mar 14, 2024
2602820
tests
Manishearth Mar 14, 2024
580e5b8
inline
Manishearth Mar 14, 2024
9718144
fix polarity
Manishearth Mar 14, 2024
dc35339
Safe Transmute: Use 'not yet supported', not 'unspecified' in errors
jswrenn Mar 15, 2024
19bc337
Add `rustc_never_type_mode` crate-level attribute to allow experimenting
WaffleLapkin Mar 15, 2024
adfdd27
Add `rustc_never_type_mode = "no_fallback"`
WaffleLapkin Mar 15, 2024
e1e719e
Mention labelled blocks in `break` docs
Wilfred Mar 15, 2024
107807d
Safe Transmute: lowercase diagnostics
jswrenn Mar 15, 2024
0754595
CI: cache PR CI Docker builds
Kobzol Mar 15, 2024
9e153cc
Rollup merge of #122254 - estebank:issue-48677, r=oli-obk
matthiaskrgr Mar 15, 2024
57f2104
Rollup merge of #122495 - Manishearth:rustdoc-👻👻👻, r=GuillaumeGomez
matthiaskrgr Mar 15, 2024
82d5b56
Rollup merge of #122543 - WaffleLapkin:never-flags, r=compiler-errors
matthiaskrgr Mar 15, 2024
b482523
Rollup merge of #122560 - jswrenn:not-yet-supported, r=compiler-errors
matthiaskrgr Mar 15, 2024
1745f3d
Rollup merge of #122562 - Wilfred:break_keyword_docs, r=workingjubilee
matthiaskrgr Mar 15, 2024
948e031
Rollup merge of #122563 - Kobzol:ci-pr-caching, r=Mark-Simulacrum
matthiaskrgr Mar 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,13 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
"`may_dangle` has unstable semantics and may be removed in the future",
),

rustc_attr!(
rustc_never_type_mode, Normal, template!(NameValueStr: "fallback_to_unit|fallback_to_niko|fallback_to_never|no_fallback"), ErrorFollowing,
@only_local: true,
"`rustc_never_type_fallback` is used to experiment with never type fallback and work on \
never type stabilization, and will never be stable"
),

// ==========================================================================
// Internal attributes: Runtime related:
// ==========================================================================
Expand Down
133 changes: 99 additions & 34 deletions compiler/rustc_hir_typeck/src/fallback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,22 @@ 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 {
/// Always fallback to `()` (aka "always spontaneous decay")
FallbackToUnit,
/// Sometimes fallback to `!`, but mainly fallback to `()` so that most of the crates are not broken.
FallbackToNiko,
/// Always fallback to `!` (which should be equivalent to never falling back + not making
/// never-to-any coercions unless necessary)
FallbackToNever,
/// Don't fallback at all
NoFallback,
}

impl<'tcx> FnCtxt<'_, 'tcx> {
/// Performs type inference fallback, setting `FnCtxt::fallback_has_occurred`
Expand Down Expand Up @@ -64,7 +78,9 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
return false;
}

let diverging_fallback = self.calculate_diverging_fallback(&unresolved_variables);
let diverging_behavior = self.diverging_fallback_behavior();
let diverging_fallback =
self.calculate_diverging_fallback(&unresolved_variables, diverging_behavior);

// We do fallback in two passes, to try to generate
// better error messages.
Expand All @@ -78,6 +94,32 @@ 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();

Expand Down Expand Up @@ -232,6 +274,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
fn calculate_diverging_fallback(
&self,
unresolved_variables: &[Ty<'tcx>],
behavior: DivergingFallbackBehavior,
) -> UnordMap<Ty<'tcx>, Ty<'tcx>> {
debug!("calculate_diverging_fallback({:?})", unresolved_variables);

Expand Down Expand Up @@ -345,39 +388,61 @@ impl<'tcx> FnCtxt<'_, 'tcx> {
output: infer_var_infos.items().any(|info| info.output),
};

if found_infer_var_info.self_in_trait && found_infer_var_info.output {
// This case falls back to () to ensure that the code pattern in
// tests/ui/never_type/fallback-closure-ret.rs continues to
// compile when never_type_fallback is enabled.
//
// This rule is not readily explainable from first principles,
// but is rather intended as a patchwork fix to ensure code
// which compiles before the stabilization of never type
// fallback continues to work.
//
// Typically this pattern is encountered in a function taking a
// closure as a parameter, where the return type of that closure
// (checked by `relationship.output`) is expected to implement
// some trait (checked by `relationship.self_in_trait`). This
// can come up in non-closure cases too, so we do not limit this
// rule to specifically `FnOnce`.
//
// When the closure's body is something like `panic!()`, the
// return type would normally be inferred to `!`. However, it
// needs to fall back to `()` in order to still compile, as the
// trait is specifically implemented for `()` but not `!`.
//
// For details on the requirements for these relationships to be
// set, see the relationship finding module in
// compiler/rustc_trait_selection/src/traits/relationships.rs.
debug!("fallback to () - found trait and projection: {:?}", diverging_vid);
diverging_fallback.insert(diverging_ty, self.tcx.types.unit);
} else if can_reach_non_diverging {
debug!("fallback to () - reached non-diverging: {:?}", diverging_vid);
diverging_fallback.insert(diverging_ty, self.tcx.types.unit);
} else {
debug!("fallback to ! - all diverging: {:?}", diverging_vid);
diverging_fallback.insert(diverging_ty, Ty::new_diverging_default(self.tcx));
use DivergingFallbackBehavior::*;
match behavior {
FallbackToUnit => {
debug!("fallback to () - legacy: {:?}", diverging_vid);
diverging_fallback.insert(diverging_ty, self.tcx.types.unit);
}
FallbackToNiko => {
if found_infer_var_info.self_in_trait && found_infer_var_info.output {
// This case falls back to () to ensure that the code pattern in
// tests/ui/never_type/fallback-closure-ret.rs continues to
// compile when never_type_fallback is enabled.
//
// This rule is not readily explainable from first principles,
// but is rather intended as a patchwork fix to ensure code
// which compiles before the stabilization of never type
// fallback continues to work.
//
// Typically this pattern is encountered in a function taking a
// closure as a parameter, where the return type of that closure
// (checked by `relationship.output`) is expected to implement
// some trait (checked by `relationship.self_in_trait`). This
// can come up in non-closure cases too, so we do not limit this
// rule to specifically `FnOnce`.
//
// When the closure's body is something like `panic!()`, the
// return type would normally be inferred to `!`. However, it
// needs to fall back to `()` in order to still compile, as the
// trait is specifically implemented for `()` but not `!`.
//
// For details on the requirements for these relationships to be
// set, see the relationship finding module in
// compiler/rustc_trait_selection/src/traits/relationships.rs.
debug!("fallback to () - found trait and projection: {:?}", diverging_vid);
diverging_fallback.insert(diverging_ty, self.tcx.types.unit);
} else if can_reach_non_diverging {
debug!("fallback to () - reached non-diverging: {:?}", diverging_vid);
diverging_fallback.insert(diverging_ty, self.tcx.types.unit);
} else {
debug!("fallback to ! - all diverging: {:?}", diverging_vid);
diverging_fallback.insert(diverging_ty, self.tcx.types.never);
}
}
FallbackToNever => {
debug!(
"fallback to ! - `rustc_never_type_mode = \"fallback_to_never\")`: {:?}",
diverging_vid
);
diverging_fallback.insert(diverging_ty, self.tcx.types.never);
}
NoFallback => {
debug!(
"no fallback - `rustc_never_type_mode = \"no_fallback\"`: {:?}",
diverging_vid
);
}
}
}

Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,9 @@ symbols! {
fadd_algebraic,
fadd_fast,
fake_variadic,
fallback_to_never,
fallback_to_niko,
fallback_to_unit,
fdiv_algebraic,
fdiv_fast,
feature,
Expand Down Expand Up @@ -1233,6 +1236,7 @@ symbols! {
no_crate_inject,
no_debug,
no_default_passes,
no_fallback,
no_implicit_prelude,
no_inline,
no_link,
Expand Down Expand Up @@ -1551,6 +1555,7 @@ symbols! {
rustc_mir,
rustc_must_implement_one_of,
rustc_never_returns_null_ptr,
rustc_never_type_mode,
rustc_no_mir_inline,
rustc_nonnull_optimization_guaranteed,
rustc_nounwind,
Expand Down