Skip to content

Commit

Permalink
fully move dropck to mir
Browse files Browse the repository at this point in the history
  • Loading branch information
lcnr committed Jul 4, 2022
1 parent a5c6a48 commit 8deadfa
Show file tree
Hide file tree
Showing 16 changed files with 79 additions and 124 deletions.
51 changes: 24 additions & 27 deletions compiler/rustc_borrowck/src/type_check/liveness/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 1,11 @@
use itertools::{Either, Itertools};
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::mir::{Body, Local};
use rustc_middle::ty::{RegionVid, TyCtxt};
use std::rc::Rc;

use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
use rustc_mir_dataflow::move_paths::MoveData;
use rustc_mir_dataflow::ResultsCursor;
use std::rc::Rc;

use crate::{
constraints::OutlivesConstraintSet,
Expand Down Expand Up @@ -46,7 46,8 @@ pub(super) fn generate<'mir, 'tcx>(
&typeck.borrowck_context.universal_regions,
&typeck.borrowck_context.constraints.outlives_constraints,
);
let live_locals = compute_live_locals(typeck.tcx(), &free_regions, &body);
let (relevant_live_locals, boring_locals) =
compute_relevant_live_locals(typeck.tcx(), &free_regions, &body);
let facts_enabled = use_polonius || AllFacts::enabled(typeck.tcx());

let polonius_drop_used = if facts_enabled {
Expand All @@ -57,48 58,44 @@ pub(super) fn generate<'mir, 'tcx>(
None
};

if !live_locals.is_empty() || facts_enabled {
trace::trace(
typeck,
body,
elements,
flow_inits,
move_data,
live_locals,
polonius_drop_used,
);
}
trace::trace(
typeck,
body,
elements,
flow_inits,
move_data,
relevant_live_locals,
boring_locals,
polonius_drop_used,
);
}

// The purpose of `compute_live_locals` is to define the subset of `Local`
// The purpose of `compute_relevant_live_locals` is to define the subset of `Local`
// variables for which we need to do a liveness computation. We only need
// to compute whether a variable `X` is live if that variable contains
// some region `R` in its type where `R` is not known to outlive a free
// region (i.e., where `R` may be valid for just a subset of the fn body).
fn compute_live_locals<'tcx>(
fn compute_relevant_live_locals<'tcx>(
tcx: TyCtxt<'tcx>,
free_regions: &FxHashSet<RegionVid>,
body: &Body<'tcx>,
) -> Vec<Local> {
let live_locals: Vec<Local> = body
.local_decls
.iter_enumerated()
.filter_map(|(local, local_decl)| {
) -> (Vec<Local>, Vec<Local>) {
let (boring_locals, relevant_live_locals): (Vec<_>, Vec<_>) =
body.local_decls.iter_enumerated().partition_map(|(local, local_decl)| {
if tcx.all_free_regions_meet(&local_decl.ty, |r| {
free_regions.contains(&r.to_region_vid())
}) {
None
Either::Left(local)
} else {
Some(local)
Either::Right(local)
}
})
.collect();
});

debug!("{} total variables", body.local_decls.len());
debug!("{} variables need liveness", live_locals.len());
debug!("{} variables need liveness", relevant_live_locals.len());
debug!("{} regions outlive free regions", free_regions.len());

live_locals
(relevant_live_locals, boring_locals)
}

/// Computes all regions that are (currently) known to outlive free
Expand Down
37 changes: 29 additions & 8 deletions compiler/rustc_borrowck/src/type_check/liveness/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 41,13 @@ pub(super) fn trace<'mir, 'tcx>(
elements: &Rc<RegionValueElements>,
flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
move_data: &MoveData<'tcx>,
live_locals: Vec<Local>,
relevant_live_locals: Vec<Local>,
boring_locals: Vec<Local>,
polonius_drop_used: Option<Vec<(Local, Location)>>,
) {
debug!("trace()");

let local_use_map = &LocalUseMap::build(&live_locals, elements, body);
let local_use_map = &LocalUseMap::build(&relevant_live_locals, elements, body);

let cx = LivenessContext {
typeck,
Expand All @@ -61,10 62,12 @@ pub(super) fn trace<'mir, 'tcx>(
let mut results = LivenessResults::new(cx);

if let Some(drop_used) = polonius_drop_used {
results.add_extra_drop_facts(drop_used, live_locals.iter().copied().collect())
results.add_extra_drop_facts(drop_used, relevant_live_locals.iter().copied().collect())
}

results.compute_for_all_locals(live_locals);
results.compute_for_all_locals(relevant_live_locals);

results.dropck_boring_locals(boring_locals);
}

/// Contextual state for the type-liveness generator.
Expand Down Expand Up @@ -133,8 136,8 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> {
}
}

fn compute_for_all_locals(&mut self, live_locals: Vec<Local>) {
for local in live_locals {
fn compute_for_all_locals(&mut self, relevant_live_locals: Vec<Local>) {
for local in relevant_live_locals {
self.reset_local_state();
self.add_defs_for(local);
self.compute_use_live_points_for(local);
Expand All @@ -157,19 160,37 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> {
}
}

// Runs dropck for locals whose liveness isn't relevant. This is
// necessary to eagerly detect unbound recursion during drop glue computation.
fn dropck_boring_locals(&mut self, boring_locals: Vec<Local>) {
for local in boring_locals {
let local_ty = self.cx.body.local_decls[local].ty;
let drop_data = self.cx.drop_data.entry(local_ty).or_insert_with({
let typeck = &mut self.cx.typeck;
move || LivenessContext::compute_drop_data(typeck, local_ty)
});

drop_data.dropck_result.report_overflows(
self.cx.typeck.infcx.tcx,
self.cx.body.local_decls[local].source_info.span,
local_ty,
);
}
}

/// Add extra drop facts needed for Polonius.
///
/// Add facts for all locals with free regions, since regions may outlive
/// the function body only at certain nodes in the CFG.
fn add_extra_drop_facts(
&mut self,
drop_used: Vec<(Local, Location)>,
live_locals: FxHashSet<Local>,
relevant_live_locals: FxHashSet<Local>,
) {
let locations = IntervalSet::new(self.cx.elements.num_points());

for (local, location) in drop_used {
if !live_locals.contains(&local) {
if !relevant_live_locals.contains(&local) {
let local_ty = self.cx.body.local_decls[local].ty;
if local_ty.has_free_regions() {
self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations);
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1825,7 1825,8 @@ rustc_queries! {
remap_env_constness
}

/// Do not call this query directly: invoke `infcx.at().dropck_outlives()` instead.
/// Do not call this query directly:
/// invoke `DropckOutlives::new(dropped_ty)).fully_perform(typeck.infcx)` instead.
query dropck_outlives(
goal: CanonicalTyGoal<'tcx>
) -> Result<
Expand Down
18 changes: 6 additions & 12 deletions compiler/rustc_typeck/src/check/dropck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 8,6 @@ use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::util::IgnoreRegions;
use rustc_middle::ty::{self, Predicate, Ty, TyCtxt};
use rustc_span::Span;
use rustc_trait_selection::traits::query::dropck_outlives::AtExt;
use rustc_trait_selection::traits::ObligationCause;

/// This function confirms that the `Drop` implementation identified by
/// `drop_impl_did` is not any more specialized than the type it is
Expand Down Expand Up @@ -234,18 232,14 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
/// This function is not only checking that the dropck obligations are met for
/// the given type, but it's also currently preventing non-regular recursion in
/// types from causing stack overflows (dropck_no_diverge_on_nonregular_*.rs).
///
/// FIXME: Completely rip out dropck and regionck.
pub(crate) fn check_drop_obligations<'a, 'tcx>(
rcx: &mut RegionCtxt<'a, 'tcx>,
ty: Ty<'tcx>,
span: Span,
body_id: hir::HirId,
_rcx: &mut RegionCtxt<'a, 'tcx>,
_ty: Ty<'tcx>,
_span: Span,
_body_id: hir::HirId,
) {
debug!("check_drop_obligations typ: {:?}", ty);

let cause = &ObligationCause::misc(span, body_id);
let infer_ok = rcx.infcx.at(cause, rcx.fcx.param_env).dropck_outlives(ty);
debug!("dropck_outlives = {:#?}", infer_ok);
rcx.fcx.register_infer_ok_obligations(infer_ok);
}

// This is an implementation of the TypeRelation trait with the
Expand Down
1 change: 0 additions & 1 deletion src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 23,4 @@ enum FingerTree<T:'static> {
fn main() {
let ft = //~ ERROR overflow while adding drop-check rules for FingerTree
FingerTree::Single(1);
//~^ ERROR overflow while adding drop-check rules for FingerTree
}
10 changes: 1 addition & 9 deletions src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 6,5 @@ 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<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<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

error: aborting due to 2 previous errors
error: aborting due to previous error

1 change: 0 additions & 1 deletion src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 22,4 @@ enum FingerTree<T:'static> {
fn main() {
let ft = //~ ERROR overflow while adding drop-check rules for FingerTree
FingerTree::Single(1);
//~^ ERROR overflow while adding drop-check rules for FingerTree
}
10 changes: 1 addition & 9 deletions src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 6,5 @@ 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<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

error[E0320]: overflow while adding drop-check rules for FingerTree<i32>
--> $DIR/dropck_no_diverge_on_nonregular_2.rs:24: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<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

error: aborting due to 2 previous errors
error: aborting due to previous error

3 changes: 1 addition & 2 deletions src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 31,5 @@ enum Wrapper<T:'static> {
fn main() {
let w = //~ ERROR overflow while adding drop-check rules for Option
Some(Wrapper::Simple::<u32>);
//~^ ERROR overflow while adding drop-check rules for Option
//~| ERROR overflow while adding drop-check rules for Wrapper
//~^ ERROR overflow while adding drop-check rules for Wrapper
}
10 changes: 1 addition & 9 deletions src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 6,6 @@ LL | let w =
|
= 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<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

error[E0320]: overflow while adding drop-check rules for Option<Wrapper<u32>>
--> $DIR/dropck_no_diverge_on_nonregular_3.rs:33:9
|
LL | Some(Wrapper::Simple::<u32>);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= 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<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

error[E0320]: overflow while adding drop-check rules for Wrapper<u32>
--> $DIR/dropck_no_diverge_on_nonregular_3.rs:33:14
|
Expand All @@ -22,5 14,5 @@ LL | Some(Wrapper::Simple::<u32>);
|
= 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<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

1 change: 0 additions & 1 deletion src/test/ui/infinite/infinite-struct.rs
Original file line number Diff line number Diff line change
@@ -1,6 1,5 @@
struct Take(Take);
//~^ ERROR has infinite size
//~| ERROR cycle detected

// check that we don't hang trying to find the tail of a recursive struct (#79437)
fn foo() -> Take {
Expand Down
14 changes: 2 additions & 12 deletions src/test/ui/infinite/infinite-struct.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 11,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Take` repre
LL | struct Take(Box<Take>);
|

error[E0391]: cycle detected when computing drop-check constraints for `Take`
--> $DIR/infinite-struct.rs:1:1
|
LL | struct Take(Take);
| ^^^^^^^^^^^
|
= note: ...which immediately requires computing drop-check constraints for `Take` again
= note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing, constness: NotConst }, value: Take } }`

error: aborting due to 2 previous errors
error: aborting due to previous error

Some errors have detailed explanations: E0072, E0391.
For more information about an error, try `rustc --explain E0072`.
For more information about this error, try `rustc --explain E0072`.
1 change: 0 additions & 1 deletion src/test/ui/infinite/infinite-tag-type-recursion.rs
Original file line number Diff line number Diff line change
@@ -1,5 1,4 @@
enum MList { Cons(isize, MList), Nil }
//~^ ERROR recursive type `MList` has infinite size
//~| ERROR cycle detected when computing drop-check constraints for `MList`

fn main() { let a = MList::Cons(10, MList::Cons(11, MList::Nil)); }
14 changes: 2 additions & 12 deletions src/test/ui/infinite/infinite-tag-type-recursion.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 11,6 @@ help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `MList` repr
LL | enum MList { Cons(isize, Box<MList>), Nil }
|

error[E0391]: cycle detected when computing drop-check constraints for `MList`
--> $DIR/infinite-tag-type-recursion.rs:1:1
|
LL | enum MList { Cons(isize, MList), Nil }
| ^^^^^^^^^^
|
= note: ...which immediately requires computing drop-check constraints for `MList` again
= note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing, constness: NotConst }, value: MList } }`

error: aborting due to 2 previous errors
error: aborting due to previous error

Some errors have detailed explanations: E0072, E0391.
For more information about an error, try `rustc --explain E0072`.
For more information about this error, try `rustc --explain E0072`.
Original file line number Diff line number Diff line change
@@ -1,18 1,14 @@
// Dropck shouldn't hit a recursion limit from checking `S<u32>` since it has
// no free regions or type parameters.
// Codegen however, has to error for the infinitely many `drop_in_place`
// functions it has been asked to create.

// build-fail
// normalize-stderr-test: ".nll/" -> "/"
// compile-flags: -Zmir-opt-level=0
// `S` is infinitely recursing so it's not possible to generate a finite
// drop impl (ignoring polymorphization).
//
// Dropck should therefore detect that this is the case and eagerly error.

struct S<T> {
t: T,
s: Box<S<fn(u: T)>>,
}

fn f(x: S<u32>) {}
fn f(x: S<u32>) {} //~ ERROR overflow while adding drop-check rules for S<u32>

fn main() {
// Force instantiation.
Expand Down
Loading

0 comments on commit 8deadfa

Please sign in to comment.