Skip to content

Commit f3cc374

Browse files
jroeschnikomatsakis
authored andcommitted
introduce fn-ctxt so we can invoke regionck code
1 parent ac968c4 commit f3cc374

File tree

3 files changed

+91
-52
lines changed

3 files changed

+91
-52
lines changed

src/librustc_typeck/check/compare_method.rs

Lines changed: 37 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use middle::free_region::FreeRegionMap;
1211
use rustc::infer::{self, InferOk, TypeOrigin};
1312
use rustc::ty;
1413
use rustc::traits::{self, Reveal};
@@ -21,6 +20,7 @@ use syntax_pos::Span;
2120

2221
use CrateCtxt;
2322
use super::assoc;
23+
use super::{Inherited, FnCtxt};
2424

2525
/// Checks that a method from an impl conforms to the signature of
2626
/// the same method as declared in the trait.
@@ -313,9 +313,6 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
313313
return;
314314
}
315315

316-
tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|mut infcx| {
317-
let mut fulfillment_cx = traits::FulfillmentContext::new();
318-
319316
// Create obligations for each predicate declared by the impl
320317
// definition in the context of the trait's parameter
321318
// environment. We can't just use `impl_env.caller_bounds`,
@@ -341,10 +338,14 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
341338
// the new hybrid bounds we computed.
342339
let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_body_id);
343340
let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.predicates);
344-
let trait_param_env =
345-
traits::normalize_param_env_or_error(tcx, trait_param_env, normalize_cause.clone());
346-
// FIXME(@jroesch) this seems ugly, but is a temporary change
347-
infcx.parameter_environment = trait_param_env;
341+
let trait_param_env = traits::normalize_param_env_or_error(tcx,
342+
trait_param_env,
343+
normalize_cause.clone());
344+
345+
tcx.infer_ctxt(None, Some(trait_param_env), Reveal::NotSpecializable).enter(|infcx| {
346+
let inh = Inherited::new(ccx, infcx);
347+
let infcx = &inh.infcx;
348+
let fulfillment_cx = &inh.fulfillment_cx;
348349

349350
debug!("compare_impl_method: caller_bounds={:?}",
350351
infcx.parameter_environment.caller_bounds);
@@ -365,7 +366,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
365366
code: traits::ObligationCauseCode::CompareImplMethodObligation,
366367
};
367368

368-
fulfillment_cx.register_predicate_obligation(
369+
fulfillment_cx.borrow_mut().register_predicate_obligation(
369370
&infcx,
370371
traits::Obligation::new(cause, predicate));
371372
}
@@ -387,30 +388,36 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
387388
let tcx = infcx.tcx;
388389
let origin = TypeOrigin::MethodCompatCheck(impl_m_span);
389390

390-
let (impl_sig, _) = infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
391-
infer::HigherRankedType,
392-
&impl_m.fty.sig);
393-
let impl_sig = impl_sig.subst(tcx, impl_to_skol_substs);
394-
let impl_sig = assoc::normalize_associated_types_in(&infcx,
395-
&mut fulfillment_cx,
396-
impl_m_span,
397-
impl_m_body_id,
398-
&impl_sig);
391+
let (impl_sig, _) =
392+
infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
393+
infer::HigherRankedType,
394+
&impl_m.fty.sig);
395+
let impl_sig =
396+
impl_sig.subst(tcx, impl_to_skol_substs);
397+
let impl_sig =
398+
assoc::normalize_associated_types_in(&infcx,
399+
&mut fulfillment_cx.borrow_mut(),
400+
impl_m_span,
401+
impl_m_body_id,
402+
&impl_sig);
399403
let impl_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
400404
unsafety: impl_m.fty.unsafety,
401405
abi: impl_m.fty.abi,
402406
sig: ty::Binder(impl_sig.clone()),
403407
}));
404408
debug!("compare_impl_method: impl_fty={:?}", impl_fty);
405409

406-
let trait_sig = tcx.liberate_late_bound_regions(infcx.parameter_environment.free_id_outlive,
407-
&trait_m.fty.sig);
408-
let trait_sig = trait_sig.subst(tcx, trait_to_skol_substs);
409-
let trait_sig = assoc::normalize_associated_types_in(&infcx,
410-
&mut fulfillment_cx,
411-
impl_m_span,
412-
impl_m_body_id,
413-
&trait_sig);
410+
let trait_sig = tcx.liberate_late_bound_regions(
411+
infcx.parameter_environment.free_id_outlive,
412+
&trait_m.fty.sig);
413+
let trait_sig =
414+
trait_sig.subst(tcx, trait_to_skol_substs);
415+
let trait_sig =
416+
assoc::normalize_associated_types_in(&infcx,
417+
&mut fulfillment_cx.borrow_mut(),
418+
impl_m_span,
419+
impl_m_body_id,
420+
&trait_sig);
414421
let trait_fty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
415422
unsafety: trait_m.fty.unsafety,
416423
abi: trait_m.fty.abi,
@@ -454,25 +461,15 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
454461

455462
// Check that all obligations are satisfied by the implementation's
456463
// version.
457-
if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) {
464+
if let Err(ref errors) = fulfillment_cx.borrow_mut().select_all_or_error(&infcx) {
458465
infcx.report_fulfillment_errors(errors);
459466
return;
460467
}
461468

462469
// Finally, resolve all regions. This catches wily misuses of
463-
// lifetime parameters. We have to build up a plausible lifetime
464-
// environment based on what we find in the trait. We could also
465-
// include the obligations derived from the method argument types,
466-
// but I don't think it's necessary -- after all, those are still
467-
// in effect when type-checking the body, and all the
468-
// where-clauses in the header etc should be implied by the trait
469-
// anyway, so it shouldn't be needed there either. Anyway, we can
470-
// always add more relations later (it's backwards compat).
471-
let mut free_regions = FreeRegionMap::new();
472-
free_regions.relate_free_regions_from_predicates(
473-
&infcx.parameter_environment.caller_bounds);
474-
475-
infcx.resolve_regions_and_report_errors(&free_regions, impl_m_body_id);
470+
// lifetime parameters.
471+
let fcx = FnCtxt::new(&inh, tcx.types.err, impl_m_body_id);
472+
fcx.regionck_item(impl_m_body_id, impl_m_span, &[]);
476473
});
477474

478475
fn check_region_bounds_on_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,

src/librustc_typeck/check/mod.rs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -407,22 +407,26 @@ impl<'a, 'gcx, 'tcx> InheritedBuilder<'a, 'gcx, 'tcx> {
407407
where F: for<'b> FnOnce(Inherited<'b, 'gcx, 'tcx>) -> R
408408
{
409409
let ccx = self.ccx;
410-
self.infcx.enter(|infcx| {
411-
f(Inherited {
412-
ccx: ccx,
413-
infcx: infcx,
414-
fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
415-
locals: RefCell::new(NodeMap()),
416-
deferred_call_resolutions: RefCell::new(DefIdMap()),
417-
deferred_cast_checks: RefCell::new(Vec::new()),
418-
anon_types: RefCell::new(DefIdMap()),
419-
deferred_obligations: RefCell::new(Vec::new()),
420-
})
421-
})
410+
self.infcx.enter(|infcx| f(Inherited::new(ccx, infcx)))
422411
}
423412
}
424413

425414
impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
415+
pub fn new(ccx: &'a CrateCtxt<'a, 'gcx>,
416+
infcx: InferCtxt<'a, 'gcx, 'tcx>)
417+
-> Self {
418+
Inherited {
419+
ccx: ccx,
420+
infcx: infcx,
421+
fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
422+
locals: RefCell::new(NodeMap()),
423+
deferred_call_resolutions: RefCell::new(DefIdMap()),
424+
deferred_cast_checks: RefCell::new(Vec::new()),
425+
anon_types: RefCell::new(DefIdMap()),
426+
deferred_obligations: RefCell::new(Vec::new()),
427+
}
428+
}
429+
426430
fn normalize_associated_types_in<T>(&self,
427431
span: Span,
428432
body_id: ast::NodeId,

src/test/compile-fail/issue-18937.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
use std::fmt;
2+
3+
#[derive(Debug)]
4+
struct MyString<'a>(&'a String);
5+
6+
struct B {
7+
list: Vec<Box<fmt::Debug>>,
8+
}
9+
10+
trait A<'a> {
11+
fn foo<F>(&mut self, f: F)
12+
where F: fmt::Debug + 'a,
13+
Self: Sized;
14+
}
15+
16+
impl<'a> A<'a> for B {
17+
fn foo<F>(&mut self, f: F) //~ ERROR parameter type `F` may not live long enough
18+
where F: fmt::Debug + 'static,
19+
{
20+
self.list.push(Box::new(f));
21+
}
22+
}
23+
24+
fn main() {
25+
let mut b = B { list: Vec::new() };
26+
27+
// Create a borrowed pointer, put it in `b`, then drop what's borrowing it
28+
let a = "hello".to_string();
29+
b.foo(MyString(&a));
30+
31+
// Drop the data which `b` has a reference to
32+
drop(a);
33+
34+
// Use the data, probably segfaulting
35+
for b in b.list.iter() {
36+
println!("{:?}", b);
37+
}
38+
}

0 commit comments

Comments
 (0)