Skip to content

Commit aa00e3a

Browse files
committed
re-introduce a cache for ast-ty-to-ty
It turns out that `ast_ty_to_ty` is supposed to be updating the `def` after it finishes, but at some point in the past it stopped doing so. This was never noticed because of the `ast_ty_to_ty_cache`, but that cache was recently removed. This PR fixes the code to update the def properly, but apparently that is not quite enough to make the operation idempotent, so for now we reintroduce the cache too. Fixes rust-lang#33425.
1 parent e88defe commit aa00e3a

File tree

6 files changed

+98
-27
lines changed

6 files changed

+98
-27
lines changed

src/librustc_resolve/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2544,6 +2544,8 @@ impl<'a> Resolver<'a> {
25442544
/// returned value. See `hir::def::PathResolution` for more info.
25452545
fn resolve_path(&mut self, id: NodeId, path: &Path, path_depth: usize, namespace: Namespace)
25462546
-> Result<PathResolution, bool /* true if an error was reported */ > {
2547+
debug!("resolve_path(id={:?} path={:?}, path_depth={:?})", id, path, path_depth);
2548+
25472549
let span = path.span;
25482550
let segments = &path.segments[..path.segments.len() - path_depth];
25492551

src/librustc_typeck/astconv.rs

+41-17
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
6464
ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope,
6565
ElisionFailureInfo, ElidedLifetime};
6666
use util::common::{ErrorReported, FN_OUTPUT_NAME};
67-
use util::nodemap::FnvHashSet;
67+
use util::nodemap::{NodeMap, FnvHashSet};
6868

6969
use rustc_const_math::ConstInt;
70-
70+
use std::cell::RefCell;
7171
use syntax::{abi, ast};
7272
use syntax::codemap::{Span, Pos};
7373
use syntax::errors::DiagnosticBuilder;
@@ -81,6 +81,9 @@ use rustc_back::slice;
8181
pub trait AstConv<'gcx, 'tcx> {
8282
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>;
8383

84+
/// A cache used for the result of `ast_ty_to_ty_cache`
85+
fn ast_ty_to_ty_cache(&self) -> &RefCell<NodeMap<Ty<'tcx>>>;
86+
8487
/// Identify the type scheme for an item with a type, like a type
8588
/// alias, fn, or struct. This allows you to figure out the set of
8689
/// type parameters defined on the item.
@@ -1416,13 +1419,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
14161419
rscope: &RegionScope,
14171420
span: Span,
14181421
param_mode: PathParamMode,
1419-
def: &Def,
1422+
def: Def,
14201423
opt_self_ty: Option<Ty<'tcx>>,
14211424
base_segments: &[hir::PathSegment])
14221425
-> Ty<'tcx> {
14231426
let tcx = self.tcx();
14241427

1425-
match *def {
1428+
debug!("base_def_to_ty(def={:?}, opt_self_ty={:?}, base_segments={:?})",
1429+
def, opt_self_ty, base_segments);
1430+
1431+
match def {
14261432
Def::Trait(trait_def_id) => {
14271433
// N.B. this case overlaps somewhat with
14281434
// TyObjectSum, see that fn for details
@@ -1515,20 +1521,27 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
15151521
rscope: &RegionScope,
15161522
span: Span,
15171523
param_mode: PathParamMode,
1518-
def: &Def,
1524+
mut def: Def,
15191525
opt_self_ty: Option<Ty<'tcx>>,
15201526
base_segments: &[hir::PathSegment],
15211527
assoc_segments: &[hir::PathSegment])
1522-
-> Ty<'tcx> {
1528+
-> (Ty<'tcx>, Def) {
1529+
debug!("finish_resolving_def_to_ty(def={:?}, \
1530+
base_segments={:?}, \
1531+
assoc_segments={:?})",
1532+
def,
1533+
base_segments,
1534+
assoc_segments);
15231535
let mut ty = self.base_def_to_ty(rscope,
15241536
span,
15251537
param_mode,
15261538
def,
15271539
opt_self_ty,
15281540
base_segments);
1529-
let mut def = *def;
1541+
debug!("finish_resolving_def_to_ty: base_def_to_ty returned {:?}", ty);
15301542
// If any associated type segments remain, attempt to resolve them.
15311543
for segment in assoc_segments {
1544+
debug!("finish_resolving_def_to_ty: segment={:?}", segment);
15321545
if ty.sty == ty::TyError {
15331546
break;
15341547
}
@@ -1540,7 +1553,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
15401553
ty = a_ty;
15411554
def = a_def;
15421555
}
1543-
ty
1556+
(ty, def)
15441557
}
15451558

15461559
/// Parses the programmer's textual representation of a type into our
@@ -1551,7 +1564,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
15511564

15521565
let tcx = self.tcx();
15531566

1554-
match ast_ty.node {
1567+
let cache = self.ast_ty_to_ty_cache();
1568+
match cache.borrow().get(&ast_ty.id) {
1569+
Some(ty) => { return ty; }
1570+
None => { }
1571+
}
1572+
1573+
let result_ty = match ast_ty.node {
15551574
hir::TyVec(ref ty) => {
15561575
tcx.mk_slice(self.ast_ty_to_ty(rscope, &ty))
15571576
}
@@ -1599,6 +1618,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
15991618
self.conv_ty_poly_trait_ref(rscope, ast_ty.span, bounds)
16001619
}
16011620
hir::TyPath(ref maybe_qself, ref path) => {
1621+
debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path);
16021622
let path_res = if let Some(&d) = tcx.def_map.borrow().get(&ast_ty.id) {
16031623
d
16041624
} else if let Some(hir::QSelf { position: 0, .. }) = *maybe_qself {
@@ -1615,13 +1635,13 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
16151635
let opt_self_ty = maybe_qself.as_ref().map(|qself| {
16161636
self.ast_ty_to_ty(rscope, &qself.ty)
16171637
});
1618-
let ty = self.finish_resolving_def_to_ty(rscope,
1619-
ast_ty.span,
1620-
PathParamMode::Explicit,
1621-
&def,
1622-
opt_self_ty,
1623-
&path.segments[..base_ty_end],
1624-
&path.segments[base_ty_end..]);
1638+
let (ty, _def) = self.finish_resolving_def_to_ty(rscope,
1639+
ast_ty.span,
1640+
PathParamMode::Explicit,
1641+
def,
1642+
opt_self_ty,
1643+
&path.segments[..base_ty_end],
1644+
&path.segments[base_ty_end..]);
16251645

16261646
if path_res.depth != 0 && ty.sty != ty::TyError {
16271647
// Write back the new resolution.
@@ -1675,7 +1695,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
16751695
// handled specially and will not descend into this routine.
16761696
self.ty_infer(None, None, None, ast_ty.span)
16771697
}
1678-
}
1698+
};
1699+
1700+
cache.borrow_mut().insert(ast_ty.id, result_ty);
1701+
1702+
result_ty
16791703
}
16801704

16811705
pub fn ty_of_arg(&self,

src/librustc_typeck/check/mod.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,8 @@ impl UnsafetyState {
346346

347347
#[derive(Clone)]
348348
pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
349+
ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>,
350+
349351
body_id: ast::NodeId,
350352

351353
// This flag is set to true if, during the writeback phase, we encounter
@@ -1262,6 +1264,10 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
12621264
impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
12631265
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
12641266

1267+
fn ast_ty_to_ty_cache(&self) -> &RefCell<NodeMap<Ty<'tcx>>> {
1268+
&self.ast_ty_to_ty_cache
1269+
}
1270+
12651271
fn get_item_type_scheme(&self, _: Span, id: DefId)
12661272
-> Result<ty::TypeScheme<'tcx>, ErrorReported>
12671273
{
@@ -1434,6 +1440,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
14341440
body_id: ast::NodeId)
14351441
-> FnCtxt<'a, 'gcx, 'tcx> {
14361442
FnCtxt {
1443+
ast_ty_to_ty_cache: RefCell::new(NodeMap()),
14371444
body_id: body_id,
14381445
writeback_errors: Cell::new(false),
14391446
err_count_on_creation: inh.tcx.sess.err_count(),
@@ -3845,15 +3852,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
38453852
if path_res.depth == 0 {
38463853
Some((opt_self_ty, &path.segments, path_res.base_def))
38473854
} else {
3848-
let mut def = path_res.base_def;
3855+
let def = path_res.base_def;
38493856
let ty_segments = path.segments.split_last().unwrap().1;
38503857
let base_ty_end = path.segments.len() - path_res.depth;
3851-
let ty = AstConv::finish_resolving_def_to_ty(self, self, span,
3852-
PathParamMode::Optional,
3853-
&mut def,
3854-
opt_self_ty,
3855-
&ty_segments[..base_ty_end],
3856-
&ty_segments[base_ty_end..]);
3858+
let (ty, _def) = AstConv::finish_resolving_def_to_ty(self, self, span,
3859+
PathParamMode::Optional,
3860+
def,
3861+
opt_self_ty,
3862+
&ty_segments[..base_ty_end],
3863+
&ty_segments[base_ty_end..]);
38573864
let item_segment = path.segments.last().unwrap();
38583865
let item_name = item_segment.identifier.name;
38593866
let def = match self.resolve_ufcs(span, item_name, ty, node_id) {

src/librustc_typeck/collect.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,12 @@ use rscope::*;
7878
use rustc::dep_graph::DepNode;
7979
use rustc::hir::map as hir_map;
8080
use util::common::{ErrorReported, MemoizationMap};
81-
use util::nodemap::FnvHashMap;
81+
use util::nodemap::{NodeMap, FnvHashMap};
8282
use {CrateCtxt, write_ty_to_tcx};
8383

8484
use rustc_const_math::ConstInt;
8585

86+
use std::cell::RefCell;
8687
use std::collections::HashSet;
8788
use std::collections::hash_map::Entry::{Occupied, Vacant};
8889
use std::rc::Rc;
@@ -146,7 +147,10 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx>
146147

147148
impl<'a,'tcx> CrateCtxt<'a,'tcx> {
148149
fn icx(&'a self, param_bounds: &'a GetTypeParameterBounds<'tcx>) -> ItemCtxt<'a,'tcx> {
149-
ItemCtxt { ccx: self, param_bounds: param_bounds }
150+
ItemCtxt {
151+
ccx: self,
152+
param_bounds: param_bounds,
153+
}
150154
}
151155

152156
fn cycle_check<F,R>(&self,
@@ -298,6 +302,10 @@ impl<'a,'tcx> ItemCtxt<'a,'tcx> {
298302
impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
299303
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { self.ccx.tcx }
300304

305+
fn ast_ty_to_ty_cache(&self) -> &RefCell<NodeMap<Ty<'tcx>>> {
306+
&self.ccx.ast_ty_to_ty_cache
307+
}
308+
301309
fn get_item_type_scheme(&self, span: Span, id: DefId)
302310
-> Result<ty::TypeScheme<'tcx>, ErrorReported>
303311
{

src/librustc_typeck/lib.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ use syntax::ast;
116116
use syntax::abi::Abi;
117117

118118
use std::cell::RefCell;
119+
use util::nodemap::NodeMap;
119120

120121
// NB: This module needs to be declared first so diagnostics are
121122
// registered before they are used.
@@ -136,7 +137,9 @@ pub struct TypeAndSubsts<'tcx> {
136137
}
137138

138139
pub struct CrateCtxt<'a, 'tcx: 'a> {
139-
// A mapping from method call sites to traits that have that method.
140+
ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>,
141+
142+
/// A mapping from method call sites to traits that have that method.
140143
pub trait_map: hir::TraitMap,
141144

142145
/// A vector of every trait accessible in the whole crate
@@ -334,6 +337,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
334337
-> CompileResult {
335338
let time_passes = tcx.sess.time_passes();
336339
let ccx = CrateCtxt {
340+
ast_ty_to_ty_cache: RefCell::new(NodeMap()),
337341
trait_map: trait_map,
338342
all_traits: RefCell::new(None),
339343
stack: RefCell::new(Vec::new()),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test the case where we resolve `C::Result` and the trait bound
12+
// itself includes a `Self::Item` shorthand.
13+
//
14+
// Regression test for issue #33425.
15+
16+
trait ParallelIterator {
17+
type Item;
18+
fn drive_unindexed<C>(self, consumer: C) -> C::Result
19+
where C: Consumer<Self::Item>;
20+
}
21+
22+
pub trait Consumer<ITEM> {
23+
type Result;
24+
}
25+
26+
fn main() { }

0 commit comments

Comments
 (0)