Skip to content

Commit 7621287

Browse files
committed
Self in where clauses may not be object safe
This is virtually certain to cause regressions, needs crater. In #50781 it was discovered that our object safety rules are not sound because we allow `Self` in where clauses without restrain. This PR is a direct fix to the rules so that we disallow methods with unsound where clauses. This currently uses hard error to measure impact, but we will want to downgrade it to a future compat error. Fixes #50781. r? @nikomatsakis
1 parent 448cc57 commit 7621287

File tree

5 files changed

+63
-37
lines changed

5 files changed

+63
-37
lines changed

src/librustc/traits/object_safety.rs

+11
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,17 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
288288
return Some(MethodViolationCode::Generic);
289289
}
290290

291+
if self.predicates_of(method.def_id).predicates.into_iter()
292+
// A trait object can't claim to live more than the concrete type,
293+
// so outlives predicates will always hold.
294+
.filter(|p| p.to_opt_type_outlives().is_none())
295+
.collect::<Vec<_>>()
296+
// Do a shallow visit so that `contains_illegal_self_type_reference`
297+
// may apply it's custom visiting.
298+
.visit_tys_shallow(|t| self.contains_illegal_self_type_reference(trait_def_id, t)) {
299+
return Some(MethodViolationCode::ReferencesSelf);
300+
}
301+
291302
None
292303
}
293304

src/librustc/ty/fold.rs

+14
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,20 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
125125
fn has_late_bound_regions(&self) -> bool {
126126
self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND)
127127
}
128+
129+
/// A visitor that does not recurse into types, works like `fn walk_shallow` in `Ty`.
130+
fn visit_tys_shallow(&self, visit: impl FnMut(Ty<'tcx>) -> bool) -> bool {
131+
132+
pub struct Visitor<F>(F);
133+
134+
impl<'tcx, F: FnMut(Ty<'tcx>) -> bool> TypeVisitor<'tcx> for Visitor<F> {
135+
fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
136+
self.0(ty)
137+
}
138+
}
139+
140+
self.visit_with(&mut Visitor(visit))
141+
}
128142
}
129143

130144
/// The TypeFolder trait defines the actual *folding*. There is a

src/test/run-pass/issue-23435.rs

-37
This file was deleted.

src/test/ui/issue-50781.rs

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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+
trait Trait {}
12+
13+
trait X {
14+
fn foo(&self) where Self: Trait;
15+
}
16+
17+
impl X for () {
18+
fn foo(&self) {}
19+
}
20+
21+
impl Trait for dyn X {}
22+
//~^ ERROR the trait `X` cannot be made into an object
23+
24+
pub fn main() {
25+
// Check that this does not segfault.
26+
<X as X>::foo(&());
27+
}

src/test/ui/issue-50781.stderr

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0038]: the trait `X` cannot be made into an object
2+
--> $DIR/issue-50781.rs:21:6
3+
|
4+
LL | impl Trait for dyn X {}
5+
| ^^^^^ the trait `X` cannot be made into an object
6+
|
7+
= note: method `foo` references the `Self` type in its arguments or return type
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0038`.

0 commit comments

Comments
 (0)