提交 02e1d5ec 编写于 作者: N Niko Matsakis

When converting parameters for an object type, be careful of defaults that reference `Self`.

Fixes #18956.
上级 f1bb6c2f
......@@ -508,13 +508,26 @@ pub fn parameterized<'tcx,GG>(cx: &ctxt<'tcx>,
// avoid those ICEs.
let generics = get_generics();
let has_self = substs.self_ty().is_some();
let tps = substs.types.get_slice(subst::TypeSpace);
let ty_params = generics.types.get_slice(subst::TypeSpace);
let has_defaults = ty_params.last().map_or(false, |def| def.default.is_some());
let num_defaults = if has_defaults {
ty_params.iter().zip(tps.iter()).rev().take_while(|&(def, &actual)| {
match def.default {
Some(default) => default.subst(cx, substs) == actual,
Some(default) => {
if !has_self && ty::type_has_self(default) {
// In an object type, there is no `Self`, and
// thus if the default value references Self,
// the user will be required to give an
// explicit value. We can't even do the
// substitution below to check without causing
// an ICE. (#18956).
false
} else {
default.subst(cx, substs) == actual
}
}
None => false
}
}).count()
......
......@@ -404,19 +404,32 @@ fn create_substs_for_ast_path<'tcx>(
let actual_supplied_ty_param_count = substs.types.len(TypeSpace);
for param in &ty_param_defs[actual_supplied_ty_param_count..] {
match param.default {
Some(default) => {
if let Some(default) = param.default {
// If we are converting an object type, then the
// `Self` parameter is unknown. However, some of the
// other type parameters may reference `Self` in their
// defaults. This will lead to an ICE if we are not
// careful!
if self_ty.is_none() && ty::type_has_self(default) {
tcx.sess.span_err(
span,
&format!("the type parameter `{}` must be explicitly specified \
in an object type because its default value `{}` references \
the type `Self`",
param.name.user_string(tcx),
default.user_string(tcx)));
substs.types.push(TypeSpace, tcx.types.err);
} else {
// This is a default type parameter.
let default = default.subst_spanned(tcx,
&substs,
Some(span));
substs.types.push(TypeSpace, default);
}
None => {
} else {
tcx.sess.span_bug(span, "extra parameter without default");
}
}
}
return substs;
}
......
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test a default that references `Self` which is then used in an
// object type. Issue #18956. In this case, the value is supplied by
// the user, but pretty-printing the type during the error message
// caused an ICE.
trait MyAdd<Rhs=Self> { fn add(&self, other: &Rhs) -> Self; }
impl MyAdd for i32 {
fn add(&self, other: &i32) -> i32 { *self + *other }
}
fn main() {
let x = 5;
let y = x as MyAdd<i32>;
//~^ ERROR as `MyAdd<i32>`
}
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test a default that references `Self` which is then used in an object type.
// Issue #18956.
#![feature(default_type_params)]
trait Foo<T=Self> {
fn method(&self);
}
fn foo(x: &Foo) { }
//~^ ERROR the type parameter `T` must be explicitly specified
fn main() { }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册