Skip to content

Commit 0e77277

Browse files
committed
Auto merge of #39939 - petrochenkov:regres, r=eddyb
Fix two ICEs in path resolution Fixes #39535 Fixes #39559 Fixes #39924 r? @eddyb
2 parents 0128be9 + 8c7d007 commit 0e77277

File tree

7 files changed

+119
-65
lines changed

7 files changed

+119
-65
lines changed

src/librustc/hir/def.rs

+26-13
Original file line numberDiff line numberDiff line change
@@ -59,32 +59,45 @@ pub enum Def {
5959
Err,
6060
}
6161

62-
/// The result of resolving a path.
63-
/// Before type checking completes, `depth` represents the number of
64-
/// trailing segments which are yet unresolved. Afterwards, if there
65-
/// were no errors, all paths should be fully resolved, with `depth`
66-
/// set to `0` and `base_def` representing the final resolution.
67-
///
62+
/// The result of resolving a path before lowering to HIR.
63+
/// `base_def` is definition of resolved part of the
64+
/// path, `unresolved_segments` is the number of unresolved
65+
/// segments.
6866
/// module::Type::AssocX::AssocY::MethodOrAssocType
6967
/// ^~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
70-
/// base_def depth = 3
68+
/// base_def unresolved_segments = 3
7169
///
7270
/// <T as Trait>::AssocX::AssocY::MethodOrAssocType
7371
/// ^~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~
74-
/// base_def depth = 2
72+
/// base_def unresolved_segments = 2
7573
#[derive(Copy, Clone, Debug)]
7674
pub struct PathResolution {
77-
pub base_def: Def,
78-
pub depth: usize
75+
base_def: Def,
76+
unresolved_segments: usize,
7977
}
8078

8179
impl PathResolution {
82-
pub fn new(def: Def) -> PathResolution {
83-
PathResolution { base_def: def, depth: 0 }
80+
pub fn new(def: Def) -> Self {
81+
PathResolution { base_def: def, unresolved_segments: 0 }
82+
}
83+
84+
pub fn with_unresolved_segments(def: Def, mut unresolved_segments: usize) -> Self {
85+
if def == Def::Err { unresolved_segments = 0 }
86+
PathResolution { base_def: def, unresolved_segments: unresolved_segments }
87+
}
88+
89+
#[inline]
90+
pub fn base_def(&self) -> Def {
91+
self.base_def
92+
}
93+
94+
#[inline]
95+
pub fn unresolved_segments(&self) -> usize {
96+
self.unresolved_segments
8497
}
8598

8699
pub fn kind_name(&self) -> &'static str {
87-
if self.depth != 0 {
100+
if self.unresolved_segments != 0 {
88101
"associated item"
89102
} else {
90103
self.base_def.kind_name()

src/librustc/hir/lowering.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -217,10 +217,10 @@ impl<'a> LoweringContext<'a> {
217217

218218
fn expect_full_def(&mut self, id: NodeId) -> Def {
219219
self.resolver.get_resolution(id).map_or(Def::Err, |pr| {
220-
if pr.depth != 0 {
220+
if pr.unresolved_segments() != 0 {
221221
bug!("path not fully resolved: {:?}", pr);
222222
}
223-
pr.base_def
223+
pr.base_def()
224224
})
225225
}
226226

@@ -421,9 +421,9 @@ impl<'a> LoweringContext<'a> {
421421
let resolution = self.resolver.get_resolution(id)
422422
.unwrap_or(PathResolution::new(Def::Err));
423423

424-
let proj_start = p.segments.len() - resolution.depth;
424+
let proj_start = p.segments.len() - resolution.unresolved_segments();
425425
let path = P(hir::Path {
426-
def: resolution.base_def,
426+
def: resolution.base_def(),
427427
segments: p.segments[..proj_start].iter().enumerate().map(|(i, segment)| {
428428
let param_mode = match (qself_position, param_mode) {
429429
(Some(j), ParamMode::Optional) if i < j => {
@@ -443,7 +443,7 @@ impl<'a> LoweringContext<'a> {
443443
index: this.def_key(def_id).parent.expect("missing parent")
444444
}
445445
};
446-
let type_def_id = match resolution.base_def {
446+
let type_def_id = match resolution.base_def() {
447447
Def::AssociatedTy(def_id) if i + 2 == proj_start => {
448448
Some(parent_def_id(self, def_id))
449449
}
@@ -474,7 +474,7 @@ impl<'a> LoweringContext<'a> {
474474

475475
// Simple case, either no projections, or only fully-qualified.
476476
// E.g. `std::mem::size_of` or `<I as Iterator>::Item`.
477-
if resolution.depth == 0 {
477+
if resolution.unresolved_segments() == 0 {
478478
return hir::QPath::Resolved(qself, path);
479479
}
480480

@@ -749,7 +749,7 @@ impl<'a> LoweringContext<'a> {
749749
bound_pred.bound_lifetimes.is_empty() => {
750750
if let Some(Def::TyParam(def_id)) =
751751
self.resolver.get_resolution(bound_pred.bounded_ty.id)
752-
.map(|d| d.base_def) {
752+
.map(|d| d.base_def()) {
753753
if let Some(node_id) =
754754
self.resolver.definitions().as_local_node_id(def_id) {
755755
for ty_param in &g.ty_params {
@@ -1295,7 +1295,7 @@ impl<'a> LoweringContext<'a> {
12951295
PatKind::Wild => hir::PatKind::Wild,
12961296
PatKind::Ident(ref binding_mode, pth1, ref sub) => {
12971297
self.with_parent_def(p.id, |this| {
1298-
match this.resolver.get_resolution(p.id).map(|d| d.base_def) {
1298+
match this.resolver.get_resolution(p.id).map(|d| d.base_def()) {
12991299
// `None` can occur in body-less function signatures
13001300
def @ None | def @ Some(Def::Local(_)) => {
13011301
let def_id = def.map(|d| d.def_id()).unwrap_or_else(|| {

src/librustc_resolve/lib.rs

+37-42
Original file line numberDiff line numberDiff line change
@@ -1195,7 +1195,8 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> {
11951195
let path: Vec<_> = segments.iter().map(|seg| Ident::with_empty_ctxt(seg.name)).collect();
11961196
match self.resolve_path(&path, Some(namespace), Some(span)) {
11971197
PathResult::Module(module) => *def = module.def().unwrap(),
1198-
PathResult::NonModule(path_res) if path_res.depth == 0 => *def = path_res.base_def,
1198+
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 =>
1199+
*def = path_res.base_def(),
11991200
PathResult::NonModule(..) => match self.resolve_path(&path, None, Some(span)) {
12001201
PathResult::Failed(msg, _) => {
12011202
resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
@@ -1718,7 +1719,7 @@ impl<'a> Resolver<'a> {
17181719
let mut new_id = None;
17191720
if let Some(trait_ref) = opt_trait_ref {
17201721
let def = self.smart_resolve_path(trait_ref.ref_id, None,
1721-
&trait_ref.path, PathSource::Trait).base_def;
1722+
&trait_ref.path, PathSource::Trait).base_def();
17221723
if def != Def::Err {
17231724
new_val = Some((def.def_id(), trait_ref.clone()));
17241725
new_id = Some(def.def_id());
@@ -1849,8 +1850,8 @@ impl<'a> Resolver<'a> {
18491850

18501851
pat.walk(&mut |pat| {
18511852
if let PatKind::Ident(binding_mode, ident, ref sub_pat) = pat.node {
1852-
if sub_pat.is_some() || match self.def_map.get(&pat.id) {
1853-
Some(&PathResolution { base_def: Def::Local(..), .. }) => true,
1853+
if sub_pat.is_some() || match self.def_map.get(&pat.id).map(|res| res.base_def()) {
1854+
Some(Def::Local(..)) => true,
18541855
_ => false,
18551856
} {
18561857
let binding_info = BindingInfo { span: ident.span, binding_mode: binding_mode };
@@ -2248,14 +2249,14 @@ impl<'a> Resolver<'a> {
22482249
let resolution = match self.resolve_qpath_anywhere(id, qself, path, ns, span,
22492250
source.defer_to_typeck(),
22502251
source.global_by_default()) {
2251-
Some(resolution) if resolution.depth == 0 => {
2252-
if is_expected(resolution.base_def) || resolution.base_def == Def::Err {
2252+
Some(resolution) if resolution.unresolved_segments() == 0 => {
2253+
if is_expected(resolution.base_def()) || resolution.base_def() == Def::Err {
22532254
resolution
22542255
} else {
22552256
// Add a temporary hack to smooth the transition to new struct ctor
22562257
// visibility rules. See #38932 for more details.
22572258
let mut res = None;
2258-
if let Def::Struct(def_id) = resolution.base_def {
2259+
if let Def::Struct(def_id) = resolution.base_def() {
22592260
if let Some((ctor_def, ctor_vis))
22602261
= self.struct_constructors.get(&def_id).cloned() {
22612262
if is_expected(ctor_def) && self.is_accessible(ctor_vis) {
@@ -2268,7 +2269,7 @@ impl<'a> Resolver<'a> {
22682269
}
22692270
}
22702271

2271-
res.unwrap_or_else(|| report_errors(self, Some(resolution.base_def)))
2272+
res.unwrap_or_else(|| report_errors(self, Some(resolution.base_def())))
22722273
}
22732274
}
22742275
Some(resolution) if source.defer_to_typeck() => {
@@ -2321,7 +2322,8 @@ impl<'a> Resolver<'a> {
23212322
match self.resolve_qpath(id, qself, path, ns, span, global_by_default) {
23222323
// If defer_to_typeck, then resolution > no resolution,
23232324
// otherwise full resolution > partial resolution > no resolution.
2324-
Some(res) if res.depth == 0 || defer_to_typeck => return Some(res),
2325+
Some(res) if res.unresolved_segments() == 0 || defer_to_typeck =>
2326+
return Some(res),
23252327
res => if fin_res.is_none() { fin_res = res },
23262328
};
23272329
}
@@ -2346,19 +2348,17 @@ impl<'a> Resolver<'a> {
23462348
if let Some(qself) = qself {
23472349
if qself.position == 0 {
23482350
// FIXME: Create some fake resolution that can't possibly be a type.
2349-
return Some(PathResolution {
2350-
base_def: Def::Mod(DefId::local(CRATE_DEF_INDEX)),
2351-
depth: path.len(),
2352-
});
2351+
return Some(PathResolution::with_unresolved_segments(
2352+
Def::Mod(DefId::local(CRATE_DEF_INDEX)), path.len()
2353+
));
23532354
}
23542355
// Make sure `A::B` in `<T as A>::B::C` is a trait item.
23552356
let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
2356-
let mut res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1],
2357-
span, PathSource::TraitItem(ns));
2358-
if res.base_def != Def::Err {
2359-
res.depth += path.len() - qself.position - 1;
2360-
}
2361-
return Some(res);
2357+
let res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1],
2358+
span, PathSource::TraitItem(ns));
2359+
return Some(PathResolution::with_unresolved_segments(
2360+
res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1
2361+
));
23622362
}
23632363

23642364
let result = match self.resolve_path(&path, Some(ns), Some(span)) {
@@ -2393,10 +2393,7 @@ impl<'a> Resolver<'a> {
23932393
}
23942394
_ => {}
23952395
}
2396-
PathResolution {
2397-
base_def: Def::PrimTy(prim),
2398-
depth: path.len() - 1,
2399-
}
2396+
PathResolution::with_unresolved_segments(Def::PrimTy(prim), path.len() - 1)
24002397
}
24012398
PathResult::Module(module) => PathResolution::new(module.def().unwrap()),
24022399
PathResult::Failed(msg, false) => {
@@ -2407,16 +2404,16 @@ impl<'a> Resolver<'a> {
24072404
PathResult::Indeterminate => bug!("indetermined path result in resolve_qpath"),
24082405
};
24092406

2410-
if path.len() > 1 && !global_by_default && result.base_def != Def::Err &&
2407+
if path.len() > 1 && !global_by_default && result.base_def() != Def::Err &&
24112408
path[0].name != keywords::CrateRoot.name() && path[0].name != "$crate" {
24122409
let unqualified_result = {
24132410
match self.resolve_path(&[*path.last().unwrap()], Some(ns), None) {
2414-
PathResult::NonModule(path_res) => path_res.base_def,
2411+
PathResult::NonModule(path_res) => path_res.base_def(),
24152412
PathResult::Module(module) => module.def().unwrap(),
24162413
_ => return Some(result),
24172414
}
24182415
};
2419-
if result.base_def == unqualified_result {
2416+
if result.base_def() == unqualified_result {
24202417
let lint = lint::builtin::UNUSED_QUALIFICATIONS;
24212418
self.session.add_lint(lint, id, span, "unnecessary qualification".to_string());
24222419
}
@@ -2470,10 +2467,9 @@ impl<'a> Resolver<'a> {
24702467
Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
24712468
Some(LexicalScopeBinding::Def(def))
24722469
if opt_ns == Some(TypeNS) || opt_ns == Some(ValueNS) => {
2473-
return PathResult::NonModule(PathResolution {
2474-
base_def: def,
2475-
depth: path.len() - 1,
2476-
});
2470+
return PathResult::NonModule(PathResolution::with_unresolved_segments(
2471+
def, path.len() - 1
2472+
));
24772473
}
24782474
_ => Err(if record_used.is_some() { Determined } else { Undetermined }),
24792475
}
@@ -2488,10 +2484,9 @@ impl<'a> Resolver<'a> {
24882484
} else if def == Def::Err {
24892485
return PathResult::NonModule(err_path_resolution());
24902486
} else if opt_ns.is_some() && (is_last || maybe_assoc) {
2491-
return PathResult::NonModule(PathResolution {
2492-
base_def: def,
2493-
depth: path.len() - i - 1,
2494-
});
2487+
return PathResult::NonModule(PathResolution::with_unresolved_segments(
2488+
def, path.len() - i - 1
2489+
));
24952490
} else {
24962491
return PathResult::Failed(format!("Not a module `{}`", ident), is_last);
24972492
}
@@ -2500,10 +2495,9 @@ impl<'a> Resolver<'a> {
25002495
Err(Determined) => {
25012496
if let Some(module) = module {
25022497
if opt_ns.is_some() && !module.is_normal() {
2503-
return PathResult::NonModule(PathResolution {
2504-
base_def: module.def().unwrap(),
2505-
depth: path.len() - i,
2506-
});
2498+
return PathResult::NonModule(PathResolution::with_unresolved_segments(
2499+
module.def().unwrap(), path.len() - i
2500+
));
25072501
}
25082502
}
25092503
let msg = if module.and_then(ModuleData::def) == self.graph_root.def() {
@@ -2672,8 +2666,9 @@ impl<'a> Resolver<'a> {
26722666
if let Some(node_id) = self.current_self_type.as_ref().and_then(extract_node_id) {
26732667
// Look for a field with the same name in the current self_type.
26742668
if let Some(resolution) = self.def_map.get(&node_id) {
2675-
match resolution.base_def {
2676-
Def::Struct(did) | Def::Union(did) if resolution.depth == 0 => {
2669+
match resolution.base_def() {
2670+
Def::Struct(did) | Def::Union(did)
2671+
if resolution.unresolved_segments() == 0 => {
26772672
if let Some(field_names) = self.field_names.get(&did) {
26782673
if field_names.iter().any(|&field_name| name == field_name) {
26792674
return Some(AssocSuggestion::Field);
@@ -3057,7 +3052,6 @@ impl<'a> Resolver<'a> {
30573052

30583053
fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) {
30593054
debug!("(recording def) recording {:?} for {}", resolution, node_id);
3060-
assert!(resolution.depth == 0 || resolution.base_def != Def::Err);
30613055
if let Some(prev_res) = self.def_map.insert(node_id, resolution) {
30623056
panic!("path resolved multiple times ({:?} before, {:?} now)", prev_res, resolution);
30633057
}
@@ -3071,7 +3065,8 @@ impl<'a> Resolver<'a> {
30713065
ty::Visibility::Restricted(self.current_module.normal_ancestor_id)
30723066
}
30733067
ast::Visibility::Restricted { ref path, id } => {
3074-
let def = self.smart_resolve_path(id, None, path, PathSource::Visibility).base_def;
3068+
let def = self.smart_resolve_path(id, None, path,
3069+
PathSource::Visibility).base_def();
30753070
if def == Def::Err {
30763071
ty::Visibility::Public
30773072
} else {

src/librustc_resolve/macros.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ impl<'a> base::Resolver for Resolver<'a> {
262262
}
263263

264264
let ext = match self.resolve_path(&path, Some(MacroNS), None) {
265-
PathResult::NonModule(path_res) => match path_res.base_def {
265+
PathResult::NonModule(path_res) => match path_res.base_def() {
266266
Def::Err => Err(Determinacy::Determined),
267267
def @ _ => Ok(self.get_macro(def)),
268268
},

src/librustc_typeck/astconv.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,19 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
918918
(_, Def::SelfTy(Some(_), Some(impl_def_id))) => {
919919
// `Self` in an impl of a trait - we have a concrete self type and a
920920
// trait reference.
921-
let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
921+
// FIXME: Self type is not always computed when we are here because type parameter
922+
// bounds may affect Self type and have to be converted before it.
923+
let trait_ref = if impl_def_id.is_local() {
924+
tcx.impl_trait_refs.borrow().get(&impl_def_id).cloned().and_then(|x| x)
925+
} else {
926+
tcx.impl_trait_ref(impl_def_id)
927+
};
928+
let trait_ref = if let Some(trait_ref) = trait_ref {
929+
trait_ref
930+
} else {
931+
tcx.sess.span_err(span, "`Self` type is used before it's determined");
932+
return (tcx.types.err, Def::Err);
933+
};
922934
let trait_ref = if let Some(free_substs) = self.get_free_substs() {
923935
trait_ref.subst(tcx, free_substs)
924936
} else {

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

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2017 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+
trait Dim {
12+
fn dim() -> usize;
13+
}
14+
15+
enum Dim3 {}
16+
17+
impl Dim for Dim3 {
18+
fn dim() -> usize {
19+
3
20+
}
21+
}
22+
23+
pub struct Vector<T, D: Dim> {
24+
entries: [T; D::dim()]
25+
//~^ ERROR cannot use an outer type parameter in this context
26+
//~| ERROR constant evaluation error
27+
}
28+
29+
fn main() {
30+
let array: [usize; Dim3::dim()] = [0; Dim3::dim()];
31+
}

src/test/compile-fail/resolve-self-in-impl.rs

+3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@ impl<T: Tr<Self>> Tr<T> for S {} //~ ERROR `Self` type is used before it's deter
1818
impl<T = Self> Tr<T> for S {} //~ ERROR `Self` type is used before it's determined
1919
impl Tr for S where Self: Copy {} //~ ERROR `Self` type is used before it's determined
2020
impl Tr for S where S<Self>: Copy {} //~ ERROR `Self` type is used before it's determined
21+
impl Tr for S where Self::Assoc: Copy {} //~ ERROR `Self` type is used before it's determined
22+
//~^ ERROR `Self` type is used before it's determined
2123
impl Tr for Self {} //~ ERROR `Self` type is used before it's determined
2224
impl Tr for S<Self> {} //~ ERROR `Self` type is used before it's determined
2325
impl Self {} //~ ERROR `Self` type is used before it's determined
2426
impl S<Self> {} //~ ERROR `Self` type is used before it's determined
27+
impl Tr<Self::Assoc> for S {} //~ ERROR `Self` type is used before it's determined
2528

2629
fn main() {}

0 commit comments

Comments
 (0)