Skip to content

Commit dbd5968

Browse files
committed
Rollup merge of rust-lang#33596 - nikomatsakis:issue-33586-regr-assoc-type-path, r=eddyb
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. r? @eddyb
2 parents 377dced + aa00e3a commit dbd5968

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
@@ -2542,6 +2542,8 @@ impl<'a> Resolver<'a> {
25422542
/// returned value. See `hir::def::PathResolution` for more info.
25432543
fn resolve_path(&mut self, id: NodeId, path: &Path, path_depth: usize, namespace: Namespace)
25442544
-> Result<PathResolution, bool /* true if an error was reported */ > {
2545+
debug!("resolve_path(id={:?} path={:?}, path_depth={:?})", id, path, path_depth);
2546+
25452547
let span = path.span;
25462548
let segments = &path.segments[..path.segments.len() - path_depth];
25472549

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
@@ -1263,6 +1265,10 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
12631265
impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
12641266
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
12651267

1268+
fn ast_ty_to_ty_cache(&self) -> &RefCell<NodeMap<Ty<'tcx>>> {
1269+
&self.ast_ty_to_ty_cache
1270+
}
1271+
12661272
fn get_item_type_scheme(&self, _: Span, id: DefId)
12671273
-> Result<ty::TypeScheme<'tcx>, ErrorReported>
12681274
{
@@ -1435,6 +1441,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
14351441
body_id: ast::NodeId)
14361442
-> FnCtxt<'a, 'gcx, 'tcx> {
14371443
FnCtxt {
1444+
ast_ty_to_ty_cache: RefCell::new(NodeMap()),
14381445
body_id: body_id,
14391446
writeback_errors: Cell::new(false),
14401447
err_count_on_creation: inh.tcx.sess.err_count(),
@@ -3852,15 +3859,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
38523859
if path_res.depth == 0 {
38533860
Some((opt_self_ty, &path.segments, path_res.base_def))
38543861
} else {
3855-
let mut def = path_res.base_def;
3862+
let def = path_res.base_def;
38563863
let ty_segments = path.segments.split_last().unwrap().1;
38573864
let base_ty_end = path.segments.len() - path_res.depth;
3858-
let ty = AstConv::finish_resolving_def_to_ty(self, self, span,
3859-
PathParamMode::Optional,
3860-
&mut def,
3861-
opt_self_ty,
3862-
&ty_segments[..base_ty_end],
3863-
&ty_segments[base_ty_end..]);
3865+
let (ty, _def) = AstConv::finish_resolving_def_to_ty(self, self, span,
3866+
PathParamMode::Optional,
3867+
def,
3868+
opt_self_ty,
3869+
&ty_segments[..base_ty_end],
3870+
&ty_segments[base_ty_end..]);
38643871
let item_segment = path.segments.last().unwrap();
38653872
let item_name = item_segment.identifier.name;
38663873
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)