Auto merge of #46657 - nikomatsakis:resolve-lifetimes-query, r=arielb1

move `resolve_lifetimes` into a proper query

Now that we made `resolve_lifetimes` into a query, elision errors no
longer abort compilation, which affects some tests.

Also, remove `dep_graph_crosscontaminate_tables` -- there is no a path in
the dep-graph, though red-green handles it. The same scenario
is (correctly) tested by issue-42602.rs in any case.

r? @michaelwoerister
This commit is contained in:
bors 2017-12-12 00:52:20 +00:00
commit 5951f8d1ba
23 changed files with 941 additions and 651 deletions

View File

@ -588,9 +588,10 @@ define_dep_nodes!( <'tcx>
[] NativeLibraryKind(DefId),
[input] LinkArgs,
[input] NamedRegion(DefIndex),
[input] IsLateBound(DefIndex),
[input] ObjectLifetimeDefaults(DefIndex),
[] ResolveLifetimes(CrateNum),
[] NamedRegion(DefIndex),
[] IsLateBound(DefIndex),
[] ObjectLifetimeDefaults(DefIndex),
[] Visibility(DefId),
[] DepKind(CrateNum),

View File

@ -28,7 +28,7 @@ pub use self::UnsafeSource::*;
pub use self::Visibility::{Public, Inherited};
use hir::def::Def;
use hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
use hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
use util::nodemap::{NodeMap, FxHashSet};
use syntax_pos::{Span, DUMMY_SP};
@ -92,6 +92,16 @@ pub struct HirId {
pub local_id: ItemLocalId,
}
impl HirId {
pub fn owner_def_id(self) -> DefId {
DefId::local(self.owner)
}
pub fn owner_local_def_id(self) -> LocalDefId {
LocalDefId::from_def_id(DefId::local(self.owner))
}
}
impl serialize::UseSpecializedEncodable for HirId {
fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
let HirId {

File diff suppressed because it is too large Load Diff

View File

@ -802,8 +802,6 @@ pub struct GlobalCtxt<'tcx> {
/// Export map produced by name resolution.
export_map: FxHashMap<DefId, Rc<Vec<Export>>>,
named_region_map: NamedRegionMap,
pub hir: hir_map::Map<'tcx>,
/// A map from DefPathHash -> DefId. Includes DefIds from the local crate
@ -986,7 +984,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
arenas: &'tcx GlobalArenas<'tcx>,
arena: &'tcx DroplessArena,
resolutions: ty::Resolutions,
named_region_map: resolve_lifetime::NamedRegionMap,
hir: hir_map::Map<'tcx>,
on_disk_query_result_cache: maps::OnDiskCache<'tcx>,
crate_name: &str,
@ -1044,27 +1041,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
.insert(hir_id.local_id,
Rc::new(StableVec::new(v)));
}
let mut defs = FxHashMap();
for (k, v) in named_region_map.defs {
let hir_id = hir.node_to_hir_id(k);
let map = defs.entry(hir_id.owner)
.or_insert_with(|| Rc::new(FxHashMap()));
Rc::get_mut(map).unwrap().insert(hir_id.local_id, v);
}
let mut late_bound = FxHashMap();
for k in named_region_map.late_bound {
let hir_id = hir.node_to_hir_id(k);
let map = late_bound.entry(hir_id.owner)
.or_insert_with(|| Rc::new(FxHashSet()));
Rc::get_mut(map).unwrap().insert(hir_id.local_id);
}
let mut object_lifetime_defaults = FxHashMap();
for (k, v) in named_region_map.object_lifetime_defaults {
let hir_id = hir.node_to_hir_id(k);
let map = object_lifetime_defaults.entry(hir_id.owner)
.or_insert_with(|| Rc::new(FxHashMap()));
Rc::get_mut(map).unwrap().insert(hir_id.local_id, Rc::new(v));
}
tls::enter_global(GlobalCtxt {
sess: s,
@ -1074,11 +1050,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
dep_graph: dep_graph.clone(),
on_disk_query_result_cache,
types: common_types,
named_region_map: NamedRegionMap {
defs,
late_bound,
object_lifetime_defaults,
},
trait_map,
export_map: resolutions.export_map.into_iter().map(|(k, v)| {
(k, Rc::new(v))
@ -2176,27 +2147,12 @@ impl<T, R, E> InternIteratorElement<T, R> for Result<T, E> {
}
}
struct NamedRegionMap {
defs: FxHashMap<DefIndex, Rc<FxHashMap<ItemLocalId, resolve_lifetime::Region>>>,
late_bound: FxHashMap<DefIndex, Rc<FxHashSet<ItemLocalId>>>,
object_lifetime_defaults:
FxHashMap<
DefIndex,
Rc<FxHashMap<ItemLocalId, Rc<Vec<ObjectLifetimeDefault>>>>,
>,
}
pub fn provide(providers: &mut ty::maps::Providers) {
// FIXME(#44234) - almost all of these queries have no sub-queries and
// therefore no actual inputs, they're just reading tables calculated in
// resolve! Does this work? Unsure! That's what the issue is about
providers.in_scope_traits_map = |tcx, id| tcx.gcx.trait_map.get(&id).cloned();
providers.module_exports = |tcx, id| tcx.gcx.export_map.get(&id).cloned();
providers.named_region_map = |tcx, id| tcx.gcx.named_region_map.defs.get(&id).cloned();
providers.is_late_bound_map = |tcx, id| tcx.gcx.named_region_map.late_bound.get(&id).cloned();
providers.object_lifetime_defaults_map = |tcx, id| {
tcx.gcx.named_region_map.object_lifetime_defaults.get(&id).cloned()
};
providers.crate_name = |tcx, id| {
assert_eq!(id, LOCAL_CRATE);
tcx.crate_name

View File

@ -443,6 +443,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::link_args<'tcx> {
}
}
impl<'tcx> QueryDescription<'tcx> for queries::resolve_lifetimes<'tcx> {
fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
format!("resolving lifetimes")
}
}
impl<'tcx> QueryDescription<'tcx> for queries::named_region_map<'tcx> {
fn describe(_tcx: TyCtxt, _: DefIndex) -> String {
format!("looking up a named region")

View File

@ -23,7 +23,7 @@ use middle::cstore::{NativeLibraryKind, DepKind, CrateSource, ExternConstBody};
use middle::privacy::AccessLevels;
use middle::reachable::ReachableSet;
use middle::region;
use middle::resolve_lifetime::{Region, ObjectLifetimeDefault};
use middle::resolve_lifetime::{ResolveLifetimes, Region, ObjectLifetimeDefault};
use middle::stability::{self, DeprecationEntry};
use middle::lang_items::{LanguageItems, LangItem};
use middle::exported_symbols::SymbolExportLevel;
@ -306,6 +306,8 @@ define_maps! { <'tcx>
-> Option<NativeLibraryKind>,
[] fn link_args: link_args_node(CrateNum) -> Rc<Vec<String>>,
// Lifetime resolution. See `middle::resolve_lifetimes`.
[] fn resolve_lifetimes: ResolveLifetimes(CrateNum) -> Rc<ResolveLifetimes>,
[] fn named_region_map: NamedRegion(DefIndex) ->
Option<Rc<FxHashMap<ItemLocalId, Region>>>,
[] fn is_late_bound_map: IsLateBound(DefIndex) ->

View File

@ -875,6 +875,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>,
DepKind::NativeLibraryKind => { force!(native_library_kind, def_id!()); }
DepKind::LinkArgs => { force!(link_args, LOCAL_CRATE); }
DepKind::ResolveLifetimes => { force!(resolve_lifetimes, krate!()); }
DepKind::NamedRegion => { force!(named_region_map, def_id!().index); }
DepKind::IsLateBound => { force!(is_late_bound_map, def_id!().index); }
DepKind::ObjectLifetimeDefaults => {

View File

@ -19,7 +19,7 @@ use rustc::session::CompileIncomplete;
use rustc::session::config::{self, Input, OutputFilenames, OutputType};
use rustc::session::search_paths::PathKind;
use rustc::lint;
use rustc::middle::{self, stability, reachable};
use rustc::middle::{self, stability, reachable, resolve_lifetime};
use rustc::middle::cstore::CrateStore;
use rustc::middle::privacy::AccessLevels;
use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas};
@ -928,6 +928,7 @@ pub fn default_provide(providers: &mut ty::maps::Providers) {
borrowck::provide(providers);
mir::provide(providers);
reachable::provide(providers);
resolve_lifetime::provide(providers);
rustc_privacy::provide(providers);
DefaultTransCrate::provide(providers);
typeck::provide(providers);
@ -984,10 +985,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(control: &CompileController,
"load query result cache",
|| rustc_incremental::load_query_result_cache(sess));
let named_region_map = time(time_passes,
"lifetime resolution",
|| middle::resolve_lifetime::krate(sess, cstore, &hir_map))?;
time(time_passes,
"looking for entry point",
|| middle::entry::find_entry_point(sess, &hir_map));
@ -1022,7 +1019,6 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(control: &CompileController,
arenas,
arena,
resolutions,
named_region_map,
hir_map,
query_result_on_disk_cache,
name,

View File

@ -18,7 +18,6 @@ use rustc_lint;
use rustc_resolve::MakeGlobMap;
use rustc_trans;
use rustc::middle::region;
use rustc::middle::resolve_lifetime;
use rustc::ty::subst::{Kind, Subst};
use rustc::traits::{ObligationCause, Reveal};
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
@ -137,7 +136,6 @@ fn test_env<F>(source_string: &str,
let hir_map = hir_map::map_crate(&sess, &*cstore, &mut hir_forest, &defs);
// run just enough stuff to build a tcx:
let named_region_map = resolve_lifetime::krate(&sess, &*cstore, &hir_map);
let (tx, _rx) = mpsc::channel();
let outputs = OutputFilenames {
out_directory: PathBuf::new(),
@ -153,7 +151,6 @@ fn test_env<F>(source_string: &str,
&arenas,
&arena,
resolutions,
named_region_map.unwrap(),
hir_map,
OnDiskCache::new_empty(sess.codemap()),
"test_crate",

View File

@ -140,7 +140,18 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
}
None => {
self.re_infer(lifetime.span, def).expect("unelided lifetime in signature")
self.re_infer(lifetime.span, def)
.unwrap_or_else(|| {
// This indicates an illegal lifetime
// elision. `resolve_lifetime` should have
// reported an error in this case -- but if
// not, let's error out.
tcx.sess.delay_span_bug(lifetime.span, "unelided lifetime in signature");
// Supply some dummy value. We don't have an
// `re_error`, annoyingly, so use `'static`.
tcx.types.re_static
})
}
};

View File

@ -1,40 +0,0 @@
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test that the `TypeckTables` nodes for impl items are independent from
// one another.
// compile-flags: -Z query-dep-graph
#![feature(rustc_attrs)]
struct Foo {
x: u8
}
impl Foo {
// Changing the item `new`...
#[rustc_if_this_changed(HirBody)]
fn new() -> Foo {
Foo { x: 0 }
}
// ...should not cause us to recompute the tables for `with`!
#[rustc_then_this_would_need(TypeckTables)] //~ ERROR no path
fn with(x: u8) -> Foo {
Foo { x: x }
}
}
fn main() {
let f = Foo::new();
let g = Foo::with(22);
assert_eq!(f.x, g.x - 22);
}

View File

@ -8,8 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
trait Trait1 {}
trait Trait2 {}
trait Trait1<'a> {}
trait Trait2<'a, 'b> {}
fn f() where
for<'a> Trait1<'a>: Trait1<'a>, // OK

View File

@ -16,8 +16,9 @@
// This was fixed by improving the resolution of the `FnOnce` trait
// selection node.
// revisions:cfail1
// revisions:cfail1 cfail2 cfail3
// compile-flags:-Zquery-dep-graph
// must-compile-successfully
#![feature(rustc_attrs)]
@ -27,16 +28,24 @@ fn main() {
}
mod a {
#[rustc_if_this_changed(HirBody)]
#[cfg(cfail1)]
pub fn foo() {
let x = vec![1, 2, 3];
let v = || ::std::mem::drop(x);
v();
}
#[cfg(not(cfail1))]
pub fn foo() {
let x = vec![1, 2, 3, 4];
let v = || ::std::mem::drop(x);
v();
}
}
mod b {
#[rustc_then_this_would_need(TypeckTables)] //[cfail1]~ ERROR no path
#[rustc_clean(cfg="cfail2")]
#[rustc_clean(cfg="cfail3")]
pub fn bar() {
let x = vec![1, 2, 3];
let v = || ::std::mem::drop(x);

View File

@ -23,6 +23,7 @@ trait Baz {
impl<T> Baz for T where T: Foo {
type Quux<'a> = <T as Foo>::Bar<'a, 'static>;
//~^ ERROR undeclared lifetime
//~| ERROR lifetime parameters are not allowed on this type [E0110]
}
fn main() {}

View File

@ -4,5 +4,11 @@ error[E0261]: use of undeclared lifetime name `'a`
24 | type Quux<'a> = <T as Foo>::Bar<'a, 'static>;
| ^^ undeclared lifetime
error: aborting due to previous error
error[E0110]: lifetime parameters are not allowed on this type
--> $DIR/construct_with_other_type.rs:24:37
|
24 | type Quux<'a> = <T as Foo>::Bar<'a, 'static>;
| ^^ lifetime parameter not allowed on this type
error: aborting due to 2 previous errors

View File

@ -4,5 +4,5 @@ error[E0261]: use of undeclared lifetime name `'a`
34 | type WithDefault<'a, T> = &'a Iterator<T>;
| ^^ undeclared lifetime
error: aborting due to previous error
error: cannot continue compilation due to previous error

View File

@ -16,8 +16,10 @@ trait Iterable {
type Item<'a>;
type Iter<'a>: Iterator<Item = Self::Item<'a>>;
//~^ ERROR undeclared lifetime
//~| ERROR lifetime parameters are not allowed on this type [E0110]
fn iter<'a>(&'a self) -> Self::Iter<'a>;
//~^ ERROR lifetime parameters are not allowed on this type [E0110]
}
fn main() {}

View File

@ -4,5 +4,17 @@ error[E0261]: use of undeclared lifetime name `'a`
17 | type Iter<'a>: Iterator<Item = Self::Item<'a>>;
| ^^ undeclared lifetime
error: aborting due to previous error
error[E0110]: lifetime parameters are not allowed on this type
--> $DIR/iterable.rs:17:47
|
17 | type Iter<'a>: Iterator<Item = Self::Item<'a>>;
| ^^ lifetime parameter not allowed on this type
error[E0110]: lifetime parameters are not allowed on this type
--> $DIR/iterable.rs:21:41
|
21 | fn iter<'a>(&'a self) -> Self::Iter<'a>;
| ^^ lifetime parameter not allowed on this type
error: aborting due to 3 previous errors