Skip to content

Commit 02e1d5e

Browse files
committed
When converting parameters for an object type, be careful of defaults that reference Self.
Fixes #18956.
1 parent f1bb6c2 commit 02e1d5e

File tree

4 files changed

+81
-6
lines changed

4 files changed

+81
-6
lines changed

src/librustc/util/ppaux.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -508,13 +508,26 @@ pub fn parameterized<'tcx,GG>(cx: &ctxt<'tcx>,
508508
// avoid those ICEs.
509509
let generics = get_generics();
510510

511+
let has_self = substs.self_ty().is_some();
511512
let tps = substs.types.get_slice(subst::TypeSpace);
512513
let ty_params = generics.types.get_slice(subst::TypeSpace);
513514
let has_defaults = ty_params.last().map_or(false, |def| def.default.is_some());
514515
let num_defaults = if has_defaults {
515516
ty_params.iter().zip(tps.iter()).rev().take_while(|&(def, &actual)| {
516517
match def.default {
517-
Some(default) => default.subst(cx, substs) == actual,
518+
Some(default) => {
519+
if !has_self && ty::type_has_self(default) {
520+
// In an object type, there is no `Self`, and
521+
// thus if the default value references Self,
522+
// the user will be required to give an
523+
// explicit value. We can't even do the
524+
// substitution below to check without causing
525+
// an ICE. (#18956).
526+
false
527+
} else {
528+
default.subst(cx, substs) == actual
529+
}
530+
}
518531
None => false
519532
}
520533
}).count()

src/librustc_typeck/astconv.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -404,17 +404,30 @@ fn create_substs_for_ast_path<'tcx>(
404404

405405
let actual_supplied_ty_param_count = substs.types.len(TypeSpace);
406406
for param in &ty_param_defs[actual_supplied_ty_param_count..] {
407-
match param.default {
408-
Some(default) => {
407+
if let Some(default) = param.default {
408+
// If we are converting an object type, then the
409+
// `Self` parameter is unknown. However, some of the
410+
// other type parameters may reference `Self` in their
411+
// defaults. This will lead to an ICE if we are not
412+
// careful!
413+
if self_ty.is_none() && ty::type_has_self(default) {
414+
tcx.sess.span_err(
415+
span,
416+
&format!("the type parameter `{}` must be explicitly specified \
417+
in an object type because its default value `{}` references \
418+
the type `Self`",
419+
param.name.user_string(tcx),
420+
default.user_string(tcx)));
421+
substs.types.push(TypeSpace, tcx.types.err);
422+
} else {
409423
// This is a default type parameter.
410424
let default = default.subst_spanned(tcx,
411425
&substs,
412426
Some(span));
413427
substs.types.push(TypeSpace, default);
414428
}
415-
None => {
416-
tcx.sess.span_bug(span, "extra parameter without default");
417-
}
429+
} else {
430+
tcx.sess.span_bug(span, "extra parameter without default");
418431
}
419432
}
420433

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2015 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 a default that references `Self` which is then used in an
12+
// object type. Issue #18956. In this case, the value is supplied by
13+
// the user, but pretty-printing the type during the error message
14+
// caused an ICE.
15+
16+
trait MyAdd<Rhs=Self> { fn add(&self, other: &Rhs) -> Self; }
17+
18+
impl MyAdd for i32 {
19+
fn add(&self, other: &i32) -> i32 { *self + *other }
20+
}
21+
22+
fn main() {
23+
let x = 5;
24+
let y = x as MyAdd<i32>;
25+
//~^ ERROR as `MyAdd<i32>`
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2015 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 a default that references `Self` which is then used in an object type.
12+
// Issue #18956.
13+
14+
#![feature(default_type_params)]
15+
16+
trait Foo<T=Self> {
17+
fn method(&self);
18+
}
19+
20+
fn foo(x: &Foo) { }
21+
//~^ ERROR the type parameter `T` must be explicitly specified
22+
23+
fn main() { }

0 commit comments

Comments
 (0)