Skip to content

Commit eee8802

Browse files
leoyvenspietroalbini
authored andcommitted
Fix self referential impl Trait substitutions
A high impact bug because a lot of common traits use a `Self` substitution by default. Should be backported to beta. There was a check for this which wasn't catching all cases, it was made more robust. Fixes #49376 Fixes #50626 r? @petrochenkov
1 parent 4a2313b commit eee8802

File tree

2 files changed

+42
-2
lines changed

2 files changed

+42
-2
lines changed

Diff for: src/librustc_privacy/lib.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@ use rustc::middle::privacy::{AccessLevel, AccessLevels};
3030
use rustc::ty::{self, TyCtxt, Ty, TypeFoldable};
3131
use rustc::ty::fold::TypeVisitor;
3232
use rustc::ty::maps::Providers;
33+
use rustc::ty::subst::UnpackedKind;
3334
use rustc::util::nodemap::NodeSet;
3435
use syntax::ast::{self, CRATE_NODE_ID, Ident};
3536
use syntax::symbol::keywords;
3637
use syntax_pos::Span;
3738

3839
use std::cmp;
3940
use std::mem::replace;
41+
use rustc_data_structures::fx::FxHashSet;
4042
use rustc_data_structures::sync::Lrc;
4143

4244
mod diagnostics;
@@ -624,6 +626,7 @@ struct TypePrivacyVisitor<'a, 'tcx: 'a> {
624626
in_body: bool,
625627
span: Span,
626628
empty_tables: &'a ty::TypeckTables<'tcx>,
629+
visited_anon_tys: FxHashSet<DefId>
627630
}
628631

629632
impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
@@ -943,8 +946,15 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
943946
self.tcx.sess.span_err(self.span, &msg);
944947
return true;
945948
}
946-
// `Self` here is the same `TyAnon`, so skip it to avoid infinite recursion
947-
for subst in trait_ref.substs.iter().skip(1) {
949+
for subst in trait_ref.substs.iter() {
950+
// Skip repeated `TyAnon`s to avoid infinite recursion.
951+
if let UnpackedKind::Type(ty) = subst.unpack() {
952+
if let ty::TyAnon(def_id, ..) = ty.sty {
953+
if !self.visited_anon_tys.insert(def_id) {
954+
continue;
955+
}
956+
}
957+
}
948958
if subst.visit_with(self) {
949959
return true;
950960
}
@@ -1677,6 +1687,7 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
16771687
in_body: false,
16781688
span: krate.span,
16791689
empty_tables: &empty_tables,
1690+
visited_anon_tys: FxHashSet()
16801691
};
16811692
intravisit::walk_crate(&mut visitor, krate);
16821693

Diff for: src/test/run-pass/impl-trait/issue-49376.rs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2018 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+
// Tests for nested self-reference which caused a stack overflow.
12+
13+
use std::fmt::Debug;
14+
use std::ops::*;
15+
16+
fn gen() -> impl PartialOrd + PartialEq + Debug { }
17+
18+
struct Bar {}
19+
trait Foo<T = Self> {}
20+
impl Foo for Bar {}
21+
22+
fn foo() -> impl Foo {
23+
Bar {}
24+
}
25+
26+
fn test_impl_ops() -> impl Add + Sub + Mul + Div { 1 }
27+
fn test_impl_assign_ops() -> impl AddAssign + SubAssign + MulAssign + DivAssign { 1 }
28+
29+
fn main() {}

0 commit comments

Comments
 (0)