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
406852a
Resolve overflow behavior for RangeFrom
CAD97 May 20, 2020
a5734ca
Override Box::<[T]>::clone_from
mendess May 23, 2020
32eedad
Add tests
mendess May 23, 2020
3ed1e79
Properly handle InlineAsmOperand::SymFn when collecting monomorphized…
Amanieu May 24, 2020
4e2696f
Only capture tokens for items with outer attributes
Aaron1011 May 25, 2020
6faa82b
Eagerly lower asm sub-expressions to HIR even if there is an error
Amanieu May 26, 2020
7aa8946
Update src/librustc_ast_lowering/expr.rs
Amanieu May 26, 2020
de53276
Fix test
Amanieu May 26, 2020
804e9e5
mir: adjust conditional in recursion limit check
davidtwco May 24, 2020
a54ed87
standardize limit comparisons with `Limit` type
davidtwco May 26, 2020
fa351ee
Fix ICE with explicit late-bound lifetimes
cofibrant May 21, 2020
dbf32e2
Remove flaky test and document the other's flakiness
mendess May 29, 2020
8ef9392
multiple Return terminators are possible
RalfJung May 25, 2020
49b1b4c
more `LocalDefId`s
lcnr May 17, 2020
35db819
Rollup merge of #72299 - lcnr:sized_help, r=petrochenkov
RalfJung May 30, 2020
93d45a0
Rollup merge of #72368 - CAD97:rangeto, r=dtolnay
RalfJung May 30, 2020
49ca99d
Rollup merge of #72441 - doctorn:late-bound-lifetime-ice, r=nikomatsakis
RalfJung May 30, 2020
8d64fd8
Rollup merge of #72499 - mendess:master, r=dtolnay
RalfJung May 30, 2020
43ae54d
Rollup merge of #72521 - Amanieu:fix-72484, r=petrochenkov
RalfJung May 30, 2020
f96e3e2
Rollup merge of #72540 - davidtwco:issue-67552-mono-collector-compari…
RalfJung May 30, 2020
6238e79
Rollup merge of #72563 - RalfJung:multi-return, r=matthewjasper
RalfJung May 30, 2020
e4c3524
Rollup merge of #72585 - Aaron1011:feature/opt-item-tokens, r=petroch…
RalfJung May 30, 2020
69310de
Rollup merge of #72607 - Amanieu:fix-72570, r=oli-obk
RalfJung May 30, 2020
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
2 changes: 1 addition & 1 deletion src/librustc_error_codes/error_codes/E0055.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ recursion limit (which can be set via the `recursion_limit` attribute).
For a somewhat artificial example:

```compile_fail,E0055
#![recursion_limit="5"]
#![recursion_limit="4"]

struct Foo;

Expand Down
4 changes: 2 additions & 2 deletions src/librustc_expand/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::sync::{self, Lrc};
use rustc_errors::{DiagnosticBuilder, ErrorReported};
use rustc_parse::{self, parser, MACRO_ARGUMENTS};
use rustc_session::parse::ParseSess;
use rustc_session::{parse::ParseSess, Limit};
use rustc_span::def_id::DefId;
use rustc_span::edition::Edition;
use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
Expand Down Expand Up @@ -941,7 +941,7 @@ pub struct ExpansionData {
pub struct ExtCtxt<'a> {
pub parse_sess: &'a ParseSess,
pub ecfg: expand::ExpansionConfig<'a>,
pub reduced_recursion_limit: Option<usize>,
pub reduced_recursion_limit: Option<Limit>,
pub root_path: PathBuf,
pub resolver: &'a mut dyn Resolver,
pub current_expansion: ExpansionData,
Expand Down
7 changes: 4 additions & 3 deletions src/librustc_expand/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use rustc_parse::validate_attr;
use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS;
use rustc_session::lint::BuiltinLintDiagnostics;
use rustc_session::parse::{feature_err, ParseSess};
use rustc_session::Limit;
use rustc_span::source_map::respan;
use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{FileName, Span, DUMMY_SP};
Expand Down Expand Up @@ -664,7 +665,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
) -> ExpandResult<AstFragment, Invocation> {
let recursion_limit =
self.cx.reduced_recursion_limit.unwrap_or(self.cx.ecfg.recursion_limit);
if self.cx.current_expansion.depth > recursion_limit {
if !recursion_limit.value_within_limit(self.cx.current_expansion.depth) {
if self.cx.reduced_recursion_limit.is_none() {
self.error_recursion_limit_reached();
}
Expand Down Expand Up @@ -1784,7 +1785,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
pub struct ExpansionConfig<'feat> {
pub crate_name: String,
pub features: Option<&'feat Features>,
pub recursion_limit: usize,
pub recursion_limit: Limit,
pub trace_mac: bool,
pub should_test: bool, // If false, strip `#[test]` nodes
pub keep_macs: bool,
Expand All @@ -1795,7 +1796,7 @@ impl<'feat> ExpansionConfig<'feat> {
ExpansionConfig {
crate_name,
features: None,
recursion_limit: 1024,
recursion_limit: Limit::new(1024),
trace_mac: false,
should_test: false,
keep_macs: false,
Expand Down
8 changes: 4 additions & 4 deletions src/librustc_middle/middle/limits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use crate::bug;
use rustc_ast::ast;
use rustc_data_structures::sync::OnceCell;
use rustc_session::Session;
use rustc_session::{Limit, Session};
use rustc_span::symbol::{sym, Symbol};

use std::num::IntErrorKind;
Expand All @@ -22,7 +22,7 @@ pub fn update_limits(sess: &Session, krate: &ast::Crate) {
fn update_limit(
sess: &Session,
krate: &ast::Crate,
limit: &OnceCell<usize>,
limit: &OnceCell<Limit>,
name: Symbol,
default: usize,
) {
Expand All @@ -34,7 +34,7 @@ fn update_limit(
if let Some(s) = attr.value_str() {
match s.as_str().parse() {
Ok(n) => {
limit.set(n).unwrap();
limit.set(Limit::new(n)).unwrap();
return;
}
Err(e) => {
Expand Down Expand Up @@ -62,5 +62,5 @@ fn update_limit(
}
}
}
limit.set(default).unwrap();
limit.set(Limit::new(default)).unwrap();
}
3 changes: 1 addition & 2 deletions src/librustc_middle/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,9 @@ fn layout_raw<'tcx>(
query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
) -> Result<&'tcx Layout, LayoutError<'tcx>> {
ty::tls::with_related_context(tcx, move |icx| {
let rec_limit = tcx.sess.recursion_limit.get().copied().unwrap();
let (param_env, ty) = query.into_parts();

if icx.layout_depth > rec_limit {
if !tcx.sess.recursion_limit().value_within_limit(icx.layout_depth) {
tcx.sess.fatal(&format!("overflow representing the type `{}`", ty));
}

Expand Down
5 changes: 3 additions & 2 deletions src/librustc_mir/const_eval/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_ast::ast::Mutability;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::AssertMessage;
use rustc_session::Limit;
use rustc_span::symbol::Symbol;

use crate::interpret::{
Expand Down Expand Up @@ -109,8 +110,8 @@ pub struct MemoryExtra {
}

impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
pub(super) fn new(const_eval_limit: usize) -> Self {
CompileTimeInterpreter { steps_remaining: const_eval_limit, stack: Vec::new() }
pub(super) fn new(const_eval_limit: Limit) -> Self {
CompileTimeInterpreter { steps_remaining: const_eval_limit.0, stack: Vec::new() }
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_mir/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
M::after_stack_push(self)?;
info!("ENTERING({}) {}", self.frame_idx(), self.frame().instance);

if self.stack().len() > self.tcx.sess.recursion_limit() {
if !self.tcx.sess.recursion_limit().value_within_limit(self.stack().len()) {
throw_exhaust!(StackFrameLimitReached)
} else {
Ok(())
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_mir/monomorphize/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ fn check_recursion_limit<'tcx>(
// Code that needs to instantiate the same function recursively
// more than the recursion limit is assumed to be causing an
// infinite expansion.
if adjusted_recursion_depth > tcx.sess.recursion_limit() {
if !tcx.sess.recursion_limit().value_within_limit(adjusted_recursion_depth) {
let error = format!("reached the recursion limit while instantiating `{}`", instance);
if let Some(def_id) = def_id.as_local() {
let hir_id = tcx.hir().as_local_hir_id(def_id);
Expand Down Expand Up @@ -463,7 +463,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
// which means that rustc basically hangs.
//
// Bail out in these cases to avoid that bad user experience.
if type_length > tcx.sess.type_length_limit() {
if !tcx.sess.type_length_limit().value_within_limit(type_length) {
// The instance name is already known to be too long for rustc.
// Show only the first and last 32 characters to avoid blasting
// the user's terminal with thousands of lines of type-name.
Expand Down
54 changes: 48 additions & 6 deletions src/librustc_session/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ use rustc_target::spec::{Target, TargetTriple, TlsModel};

use std::cell::{self, RefCell};
use std::env;
use std::fmt;
use std::io::Write;
use std::num::NonZeroU32;
use std::ops::{Div, Mul};
use std::path::PathBuf;
use std::str::FromStr;
use std::sync::Arc;
Expand All @@ -55,6 +57,46 @@ pub enum CtfeBacktrace {
Immediate,
}

/// New-type wrapper around `usize` for representing limits. Ensures that comparisons against
/// limits are consistent throughout the compiler.
#[derive(Clone, Copy, Debug)]
pub struct Limit(pub usize);

impl Limit {
/// Create a new limit from a `usize`.
pub fn new(value: usize) -> Self {
Limit(value)
}

/// Check that `value` is within the limit. Ensures that the same comparisons are used
/// throughout the compiler, as mismatches can cause ICEs, see #72540.
pub fn value_within_limit(&self, value: usize) -> bool {
value <= self.0
}
}

impl fmt::Display for Limit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}

impl Div<usize> for Limit {
type Output = Limit;

fn div(self, rhs: usize) -> Self::Output {
Limit::new(self.0 / rhs)
}
}

impl Mul<usize> for Limit {
type Output = Limit;

fn mul(self, rhs: usize) -> Self::Output {
Limit::new(self.0 * rhs)
}
}

/// Represents the data associated with a compilation
/// session for a single crate.
pub struct Session {
Expand Down Expand Up @@ -89,13 +131,13 @@ pub struct Session {

/// The maximum recursion limit for potentially infinitely recursive
/// operations such as auto-dereference and monomorphization.
pub recursion_limit: OnceCell<usize>,
pub recursion_limit: OnceCell<Limit>,

/// The maximum length of types during monomorphization.
pub type_length_limit: OnceCell<usize>,
pub type_length_limit: OnceCell<Limit>,

/// The maximum blocks a const expression can evaluate.
pub const_eval_limit: OnceCell<usize>,
pub const_eval_limit: OnceCell<Limit>,

incr_comp_session: OneThread<RefCell<IncrCompSession>>,
/// Used for incremental compilation tests. Will only be populated if
Expand Down Expand Up @@ -255,15 +297,15 @@ impl Session {
self.crate_types.set(crate_types).expect("`crate_types` was initialized twice")
}

pub fn recursion_limit(&self) -> usize {
pub fn recursion_limit(&self) -> Limit {
self.recursion_limit.get().copied().unwrap()
}

pub fn type_length_limit(&self) -> usize {
pub fn type_length_limit(&self) -> Limit {
self.type_length_limit.get().copied().unwrap()
}

pub fn const_eval_limit(&self) -> usize {
pub fn const_eval_limit(&self) -> Limit {
self.const_eval_limit.get().copied().unwrap()
}

Expand Down
9 changes: 4 additions & 5 deletions src/librustc_trait_selection/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,10 +333,10 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {

Reveal::All => {
let recursion_limit = self.tcx().sess.recursion_limit();
if self.depth >= recursion_limit {
if !recursion_limit.value_within_limit(self.depth) {
let obligation = Obligation::with_depth(
self.cause.clone(),
recursion_limit,
recursion_limit.0,
self.param_env,
ty,
);
Expand Down Expand Up @@ -522,7 +522,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
// But for now, let's classify this as an overflow:
let recursion_limit = selcx.tcx().sess.recursion_limit();
let obligation =
Obligation::with_depth(cause, recursion_limit, param_env, projection_ty);
Obligation::with_depth(cause, recursion_limit.0, param_env, projection_ty);
selcx.infcx().report_overflow_error(&obligation, false);
}
Err(ProjectionCacheEntry::NormalizedTy(ty)) => {
Expand Down Expand Up @@ -814,8 +814,7 @@ fn project_type<'cx, 'tcx>(
) -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>> {
debug!("project(obligation={:?})", obligation);

let recursion_limit = selcx.tcx().sess.recursion_limit();
if obligation.recursion_depth >= recursion_limit {
if !selcx.tcx().sess.recursion_limit().value_within_limit(obligation.recursion_depth) {
debug!("project: overflow!");
return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
}
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_trait_selection/traits/query/normalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,10 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {

Reveal::All => {
let recursion_limit = self.tcx().sess.recursion_limit();
if self.anon_depth >= recursion_limit {
if !recursion_limit.value_within_limit(self.anon_depth) {
let obligation = Obligation::with_depth(
self.cause.clone(),
recursion_limit,
recursion_limit.0,
self.param_env,
ty,
);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trait_selection/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -919,7 +919,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &Obligation<'tcx, T>,
error_obligation: &Obligation<'tcx, V>,
) -> Result<(), OverflowError> {
if obligation.recursion_depth >= self.infcx.tcx.sess.recursion_limit() {
if !self.infcx.tcx.sess.recursion_limit().value_within_limit(obligation.recursion_depth) {
match self.query_mode {
TraitQueryMode::Standard => {
self.infcx().report_overflow_error(error_obligation, true);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_traits/dropck_outlives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ fn dtorck_constraint_for_ty<'tcx>(
) -> Result<(), NoSolution> {
debug!("dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})", span, for_ty, depth, ty);

if depth >= tcx.sess.recursion_limit() {
if !tcx.sess.recursion_limit().value_within_limit(depth) {
constraints.overflows.push(ty);
return Ok(());
}
Expand Down
5 changes: 3 additions & 2 deletions src/librustc_ty/needs_drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use rustc_hir::def_id::DefId;
use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::Limit;
use rustc_span::DUMMY_SP;

type NeedsDropResult<T> = Result<T, AlwaysRequiresDrop>;
Expand All @@ -30,7 +31,7 @@ struct NeedsDropTypes<'tcx, F> {
/// if it needs drop. If the result depends on whether some other types
/// need drop we push them onto the stack.
unchecked_tys: Vec<(Ty<'tcx>, usize)>,
recursion_limit: usize,
recursion_limit: Limit,
adt_components: F,
}

Expand Down Expand Up @@ -66,7 +67,7 @@ where
let tcx = self.tcx;

while let Some((ty, level)) = self.unchecked_tys.pop() {
if level > self.recursion_limit {
if !self.recursion_limit.value_within_limit(level) {
// Not having a `Span` isn't great. But there's hopefully some other
// recursion limit error as well.
tcx.sess.span_err(
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/autoderef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
return Some((self.cur_ty, 0));
}

if self.steps.len() >= tcx.sess.recursion_limit() {
if !tcx.sess.recursion_limit().value_within_limit(self.steps.len()) {
if !self.silence_errors {
report_autoderef_recursion_limit_error(tcx, self.span, self.cur_ty);
}
Expand Down
3 changes: 2 additions & 1 deletion src/test/ui/did_you_mean/recursion_limit.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0275]: overflow evaluating the requirement `J: std::marker::Send`
error[E0275]: overflow evaluating the requirement `K: std::marker::Send`
--> $DIR/recursion_limit.rs:34:5
|
LL | fn is_send<T:Send>() { }
Expand All @@ -8,6 +8,7 @@ LL | is_send::<A>();
| ^^^^^^^^^^^^
|
= help: consider adding a `#![recursion_limit="20"]` attribute to your crate (`recursion_limit`)
= note: required because it appears within the type `J`
= note: required because it appears within the type `I`
= note: required because it appears within the type `H`
= note: required because it appears within the type `G`
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/did_you_mean/recursion_limit_deref.stderr
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
error[E0055]: reached the recursion limit while auto-dereferencing `I`
error[E0055]: reached the recursion limit while auto-dereferencing `J`
--> $DIR/recursion_limit_deref.rs:50:22
|
LL | let x: &Bottom = &t;
Expand Down
4 changes: 2 additions & 2 deletions src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ error[E0320]: overflow while adding drop-check rules for FingerTree<i32>
LL | let ft =
| ^^
|
= note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
= note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

error[E0320]: overflow while adding drop-check rules for FingerTree<i32>
--> $DIR/dropck_no_diverge_on_nonregular_1.rs:25:9
|
LL | FingerTree::Single(1);
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
= note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

error: aborting due to 2 previous errors

Loading