rustc: store type parameter defaults outside of ty::Generics.
This commit is contained in:
parent
1572bf104d
commit
e8d01ea4c7
34 changed files with 394 additions and 385 deletions
|
|
@ -42,7 +42,7 @@ use std::cell::RefCell;
|
|||
use std::iter;
|
||||
use syntax::{abi, ast};
|
||||
use syntax::feature_gate::{GateIssue, emit_feature_err};
|
||||
use syntax::symbol::{Symbol, keywords};
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::Span;
|
||||
|
||||
pub trait AstConv<'gcx, 'tcx> {
|
||||
|
|
@ -53,7 +53,7 @@ pub trait AstConv<'gcx, 'tcx> {
|
|||
|
||||
/// Returns the generic type and lifetime parameters for an item.
|
||||
fn get_generics(&self, span: Span, id: DefId)
|
||||
-> Result<&'tcx ty::Generics<'tcx>, ErrorReported>;
|
||||
-> Result<&'tcx ty::Generics, ErrorReported>;
|
||||
|
||||
/// Identify the type for an item, like a type alias, fn, or struct.
|
||||
fn get_item_type(&self, span: Span, id: DefId) -> Result<Ty<'tcx>, ErrorReported>;
|
||||
|
|
@ -89,7 +89,7 @@ pub trait AstConv<'gcx, 'tcx> {
|
|||
|
||||
/// Same as ty_infer, but with a known type parameter definition.
|
||||
fn ty_infer_for_def(&self,
|
||||
_def: &ty::TypeParameterDef<'tcx>,
|
||||
_def: &ty::TypeParameterDef,
|
||||
_substs: &[Kind<'tcx>],
|
||||
span: Span) -> Ty<'tcx> {
|
||||
self.ty_infer(span)
|
||||
|
|
@ -277,9 +277,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
}
|
||||
|
||||
let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF);
|
||||
let default_needs_object_self = |p: &ty::TypeParameterDef<'tcx>| {
|
||||
if let Some(ref default) = p.default {
|
||||
if is_object && default.has_self_ty() {
|
||||
let default_needs_object_self = |p: &ty::TypeParameterDef| {
|
||||
if is_object && p.has_default {
|
||||
let default = self.get_item_type(span, p.def_id).ok();
|
||||
if default.has_self_ty() {
|
||||
// There is no suitable inference default for a type parameter
|
||||
// that references self, in an object type.
|
||||
return true;
|
||||
|
|
@ -327,7 +328,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
self.ty_infer(span)
|
||||
};
|
||||
ty_var
|
||||
} else if let Some(default) = def.default {
|
||||
} else if def.has_default {
|
||||
// No type parameter provided, but a default exists.
|
||||
|
||||
// If we are converting an object type, then the
|
||||
|
|
@ -346,7 +347,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
tcx.types.err
|
||||
} else {
|
||||
// This is a default type parameter.
|
||||
default.subst_spanned(tcx, substs, Some(span))
|
||||
match self.get_item_type(span, def.def_id) {
|
||||
Ok(ty) => ty.subst_spanned(tcx, substs, Some(span)),
|
||||
Err(ErrorReported) => tcx.types.err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We've already errored above about the mismatch.
|
||||
|
|
@ -954,19 +958,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
Err(ErrorReported) => return (tcx.types.err, Def::Err),
|
||||
}
|
||||
}
|
||||
(&ty::TyParam(_), Def::SelfTy(Some(trait_did), None)) => {
|
||||
let trait_node_id = tcx.hir.as_local_node_id(trait_did).unwrap();
|
||||
match self.find_bound_for_assoc_item(trait_node_id,
|
||||
keywords::SelfType.name(),
|
||||
assoc_name,
|
||||
span) {
|
||||
Ok(bound) => bound,
|
||||
Err(ErrorReported) => return (tcx.types.err, Def::Err),
|
||||
}
|
||||
}
|
||||
(&ty::TyParam(_), Def::SelfTy(Some(param_did), None)) |
|
||||
(&ty::TyParam(_), Def::TyParam(param_did)) => {
|
||||
let param_node_id = tcx.hir.as_local_node_id(param_did).unwrap();
|
||||
let param_name = tcx.type_parameter_def(param_node_id).name;
|
||||
let param_name = ::ty_param_name(tcx, param_node_id);
|
||||
match self.find_bound_for_assoc_item(param_node_id,
|
||||
param_name,
|
||||
assoc_name,
|
||||
|
|
@ -1063,21 +1058,14 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
tcx.prohibit_type_params(&path.segments);
|
||||
|
||||
let node_id = tcx.hir.as_local_node_id(did).unwrap();
|
||||
let param = tcx.ty_param_defs.borrow().get(&node_id)
|
||||
.map(ty::ParamTy::for_def);
|
||||
if let Some(p) = param {
|
||||
p.to_ty(tcx)
|
||||
} else {
|
||||
// Only while computing defaults of earlier type
|
||||
// parameters can a type parameter be missing its def.
|
||||
struct_span_err!(tcx.sess, span, E0128,
|
||||
"type parameters with a default cannot use \
|
||||
forward declared identifiers")
|
||||
.span_label(span, &format!("defaulted type parameters \
|
||||
cannot be forward declared"))
|
||||
.emit();
|
||||
tcx.types.err
|
||||
}
|
||||
let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id));
|
||||
let index = match self.get_generics(span, item_def_id) {
|
||||
Ok(generics) => {
|
||||
generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index]
|
||||
}
|
||||
Err(ErrorReported) => return tcx.types.err
|
||||
};
|
||||
tcx.mk_param(index, ::ty_param_name(tcx, node_id))
|
||||
}
|
||||
Def::SelfTy(_, Some(def_id)) => {
|
||||
// Self in impl (we know the concrete type).
|
||||
|
|
@ -1510,7 +1498,7 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
|||
fn check_type_argument_count(tcx: TyCtxt, span: Span, supplied: usize,
|
||||
ty_param_defs: &[ty::TypeParameterDef]) {
|
||||
let accepted = ty_param_defs.len();
|
||||
let required = ty_param_defs.iter().take_while(|x| x.default.is_none()) .count();
|
||||
let required = ty_param_defs.iter().take_while(|x| !x.has_default).count();
|
||||
if supplied < required {
|
||||
let expected = if required < accepted {
|
||||
"expected at least"
|
||||
|
|
|
|||
|
|
@ -386,8 +386,8 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||
fn check_region_bounds_on_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
span: Span,
|
||||
impl_m: &ty::AssociatedItem,
|
||||
trait_generics: &ty::Generics<'tcx>,
|
||||
impl_generics: &ty::Generics<'tcx>,
|
||||
trait_generics: &ty::Generics,
|
||||
impl_generics: &ty::Generics,
|
||||
trait_to_skol_substs: &Substs<'tcx>,
|
||||
impl_to_skol_substs: &Substs<'tcx>)
|
||||
-> Result<(), ErrorReported> {
|
||||
|
|
|
|||
|
|
@ -1360,7 +1360,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn get_generics(&self, _: Span, id: DefId)
|
||||
-> Result<&'tcx ty::Generics<'tcx>, ErrorReported>
|
||||
-> Result<&'tcx ty::Generics, ErrorReported>
|
||||
{
|
||||
Ok(self.tcx().item_generics(id))
|
||||
}
|
||||
|
|
@ -1390,14 +1390,17 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
|
|||
node_id: ast::NodeId)
|
||||
-> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
|
||||
{
|
||||
let def = self.tcx.type_parameter_def(node_id);
|
||||
let tcx = self.tcx;
|
||||
let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id));
|
||||
let generics = tcx.item_generics(item_def_id);
|
||||
let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index];
|
||||
let r = self.parameter_environment
|
||||
.caller_bounds
|
||||
.iter()
|
||||
.filter_map(|predicate| {
|
||||
match *predicate {
|
||||
ty::Predicate::Trait(ref data) => {
|
||||
if data.0.self_ty().is_param(def.index) {
|
||||
if data.0.self_ty().is_param(index) {
|
||||
Some(data.to_poly_trait_ref())
|
||||
} else {
|
||||
None
|
||||
|
|
@ -1426,7 +1429,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn ty_infer_for_def(&self,
|
||||
ty_param_def: &ty::TypeParameterDef<'tcx>,
|
||||
ty_param_def: &ty::TypeParameterDef,
|
||||
substs: &[Kind<'tcx>],
|
||||
span: Span) -> Ty<'tcx> {
|
||||
self.type_var_for_def(span, ty_param_def, substs)
|
||||
|
|
@ -4423,8 +4426,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
if let Some(ast_ty) = types.get(i) {
|
||||
// A provided type parameter.
|
||||
self.to_ty(ast_ty)
|
||||
} else if let (false, Some(default)) = (infer_types, def.default) {
|
||||
} else if !infer_types && def.has_default {
|
||||
// No type parameter provided, but a default exists.
|
||||
let default = self.tcx.item_type(def.def_id);
|
||||
default.subst_spanned(self.tcx, substs, Some(span))
|
||||
} else {
|
||||
// No type parameters were provided, we can infer all.
|
||||
|
|
@ -4537,9 +4541,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
&generics.types
|
||||
}
|
||||
});
|
||||
let required_len = type_defs.iter()
|
||||
.take_while(|d| d.default.is_none())
|
||||
.count();
|
||||
let required_len = type_defs.iter().take_while(|d| !d.has_default).count();
|
||||
if types.len() > type_defs.len() {
|
||||
let span = types[type_defs.len()].span;
|
||||
let expected_text = count_type_params(type_defs.len());
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ use lint;
|
|||
use constrained_type_params as ctp;
|
||||
use middle::lang_items::SizedTraitLangItem;
|
||||
use middle::const_val::ConstVal;
|
||||
use middle::resolve_lifetime as rl;
|
||||
use rustc_const_eval::EvalHint::UncheckedExprHint;
|
||||
use rustc_const_eval::{ConstContext, report_const_eval_err};
|
||||
use rustc::ty::subst::Substs;
|
||||
|
|
@ -76,6 +77,7 @@ use CrateCtxt;
|
|||
use rustc_const_math::ConstInt;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use syntax::{abi, ast, attr};
|
||||
use syntax::symbol::{Symbol, keywords};
|
||||
|
|
@ -186,6 +188,16 @@ impl<'a, 'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'a, 'tcx> {
|
|||
intravisit::walk_item(self, item);
|
||||
}
|
||||
|
||||
fn visit_generics(&mut self, generics: &'tcx hir::Generics) {
|
||||
for param in &generics.ty_params {
|
||||
if param.default.is_some() {
|
||||
let def_id = self.ccx.tcx.hir.local_def_id(param.id);
|
||||
type_of_def_id(self.ccx, def_id);
|
||||
}
|
||||
}
|
||||
intravisit::walk_generics(self, generics);
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
|
||||
if let hir::ExprClosure(..) = expr.node {
|
||||
let def_id = self.ccx.tcx.hir.local_def_id(expr.id);
|
||||
|
|
@ -277,11 +289,10 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
|
|||
tcx.item_path_str(def_id)));
|
||||
}
|
||||
AstConvRequest::GetTypeParameterBounds(id) => {
|
||||
let def = tcx.type_parameter_def(id);
|
||||
err.note(
|
||||
&format!("the cycle begins when computing the bounds \
|
||||
for type parameter `{}`...",
|
||||
def.name));
|
||||
::ty_param_name(tcx, id)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -300,11 +311,10 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
|
|||
tcx.item_path_str(def_id)));
|
||||
}
|
||||
AstConvRequest::GetTypeParameterBounds(id) => {
|
||||
let def = tcx.type_parameter_def(id);
|
||||
err.note(
|
||||
&format!("...which then requires computing the bounds \
|
||||
for type parameter `{}`...",
|
||||
def.name));
|
||||
::ty_param_name(tcx, id)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -324,11 +334,10 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
|
|||
tcx.item_path_str(def_id)));
|
||||
}
|
||||
AstConvRequest::GetTypeParameterBounds(id) => {
|
||||
let def = tcx.type_parameter_def(id);
|
||||
err.note(
|
||||
&format!("...which then again requires computing the bounds \
|
||||
for type parameter `{}`, completing the cycle.",
|
||||
def.name));
|
||||
::ty_param_name(tcx, id)));
|
||||
}
|
||||
}
|
||||
err.emit();
|
||||
|
|
@ -385,7 +394,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn get_generics(&self, span: Span, id: DefId)
|
||||
-> Result<&'tcx ty::Generics<'tcx>, ErrorReported>
|
||||
-> Result<&'tcx ty::Generics, ErrorReported>
|
||||
{
|
||||
self.ccx.cycle_check(span, AstConvRequest::GetGenerics(id), || {
|
||||
Ok(generics_of_def_id(self.ccx, id))
|
||||
|
|
@ -531,20 +540,23 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
|
|||
node_id: ast::NodeId)
|
||||
-> Vec<ty::Predicate<'tcx>>
|
||||
{
|
||||
let def = astconv.tcx().type_parameter_def(node_id);
|
||||
let tcx = astconv.tcx();
|
||||
let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id));
|
||||
let generics = tcx.item_generics(item_def_id);
|
||||
let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index];
|
||||
|
||||
let mut results = self.parent.map_or(vec![], |def_id| {
|
||||
let parent = astconv.tcx().item_predicates(def_id);
|
||||
let parent = tcx.item_predicates(def_id);
|
||||
parent.get_type_parameter_bounds(astconv, span, node_id)
|
||||
});
|
||||
|
||||
results.extend(self.predicates.iter().filter(|predicate| {
|
||||
match **predicate {
|
||||
ty::Predicate::Trait(ref data) => {
|
||||
data.skip_binder().self_ty().is_param(def.index)
|
||||
data.skip_binder().self_ty().is_param(index)
|
||||
}
|
||||
ty::Predicate::TypeOutlives(ref data) => {
|
||||
data.skip_binder().0.is_param(def.index)
|
||||
data.skip_binder().0.is_param(index)
|
||||
}
|
||||
ty::Predicate::Equate(..) |
|
||||
ty::Predicate::RegionOutlives(..) |
|
||||
|
|
@ -568,7 +580,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
|
|||
impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics {
|
||||
fn get_type_parameter_bounds(&self,
|
||||
astconv: &AstConv<'tcx, 'tcx>,
|
||||
_: Span,
|
||||
span: Span,
|
||||
node_id: ast::NodeId)
|
||||
-> Vec<ty::Predicate<'tcx>>
|
||||
{
|
||||
|
|
@ -576,8 +588,15 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics {
|
|||
// written inline like `<T:Foo>` or in a where clause like
|
||||
// `where T:Foo`.
|
||||
|
||||
let def = astconv.tcx().type_parameter_def(node_id);
|
||||
let ty = astconv.tcx().mk_param_from_def(&def);
|
||||
let tcx = astconv.tcx();
|
||||
let item_def_id = tcx.hir.local_def_id(::ty_param_owner(tcx, node_id));
|
||||
let index = match astconv.get_generics(span, item_def_id) {
|
||||
Ok(generics) => {
|
||||
generics.type_param_to_index[&tcx.hir.local_def_id(node_id).index]
|
||||
}
|
||||
Err(ErrorReported) => return vec![]
|
||||
};
|
||||
let ty = tcx.mk_param(index, ::ty_param_name(tcx, node_id));
|
||||
|
||||
let from_ty_params =
|
||||
self.ty_params
|
||||
|
|
@ -594,7 +613,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics {
|
|||
hir::WherePredicate::BoundPredicate(ref bp) => Some(bp),
|
||||
_ => None
|
||||
})
|
||||
.filter(|bp| is_param(astconv.tcx(), &bp.bounded_ty, node_id))
|
||||
.filter(|bp| is_param(tcx, &bp.bounded_ty, node_id))
|
||||
.flat_map(|bp| bp.bounds.iter())
|
||||
.flat_map(|b| predicates_from_bound(astconv, ty, b));
|
||||
|
||||
|
|
@ -625,7 +644,7 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
}
|
||||
|
||||
fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
struct_generics: &'tcx ty::Generics<'tcx>,
|
||||
struct_generics: &'tcx ty::Generics,
|
||||
struct_predicates: &ty::GenericPredicates<'tcx>,
|
||||
field: &hir::StructField,
|
||||
ty_f: &'tcx ty::FieldDef)
|
||||
|
|
@ -938,7 +957,7 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||
fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
def: &'tcx ty::AdtDef,
|
||||
ty: Ty<'tcx>,
|
||||
generics: &'tcx ty::Generics<'tcx>,
|
||||
generics: &'tcx ty::Generics,
|
||||
predicates: ty::GenericPredicates<'tcx>,
|
||||
variants: &[hir::Variant]) {
|
||||
// fill the field types
|
||||
|
|
@ -1325,7 +1344,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item)
|
|||
|
||||
fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
def_id: DefId)
|
||||
-> &'tcx ty::Generics<'tcx> {
|
||||
-> &'tcx ty::Generics {
|
||||
let tcx = ccx.tcx;
|
||||
let node_id = if let Some(id) = tcx.hir.as_local_node_id(def_id) {
|
||||
id
|
||||
|
|
@ -1402,18 +1421,14 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||
// the node id for the Self type parameter.
|
||||
let param_id = item.id;
|
||||
|
||||
let parent = ccx.tcx.hir.get_parent(param_id);
|
||||
|
||||
let def = ty::TypeParameterDef {
|
||||
opt_self = Some(ty::TypeParameterDef {
|
||||
index: 0,
|
||||
name: keywords::SelfType.name(),
|
||||
def_id: tcx.hir.local_def_id(param_id),
|
||||
default_def_id: tcx.hir.local_def_id(parent),
|
||||
default: None,
|
||||
has_default: false,
|
||||
object_lifetime_default: rl::Set1::Empty,
|
||||
pure_wrt_drop: false,
|
||||
};
|
||||
tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
|
||||
opt_self = Some(def);
|
||||
});
|
||||
|
||||
allow_defaults = true;
|
||||
generics
|
||||
|
|
@ -1459,11 +1474,36 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||
}
|
||||
}).collect::<Vec<_>>();
|
||||
|
||||
let object_lifetime_defaults =
|
||||
tcx.named_region_map.object_lifetime_defaults.get(&node_id);
|
||||
|
||||
// Now create the real type parameters.
|
||||
let type_start = own_start + regions.len() as u32;
|
||||
let types = ast_generics.ty_params.iter().enumerate().map(|(i, p)| {
|
||||
let i = type_start + i as u32;
|
||||
get_or_create_type_parameter_def(ccx, i, p, allow_defaults)
|
||||
if p.name == keywords::SelfType.name() {
|
||||
span_bug!(p.span, "`Self` should not be the name of a regular parameter");
|
||||
}
|
||||
|
||||
if !allow_defaults && p.default.is_some() {
|
||||
if !tcx.sess.features.borrow().default_type_parameter_fallback {
|
||||
tcx.sess.add_lint(
|
||||
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
|
||||
p.id,
|
||||
p.span,
|
||||
format!("defaults for type parameters are only allowed in `struct`, \
|
||||
`enum`, `type`, or `trait` definitions."));
|
||||
}
|
||||
}
|
||||
|
||||
ty::TypeParameterDef {
|
||||
index: type_start + i as u32,
|
||||
name: p.name,
|
||||
def_id: tcx.hir.local_def_id(p.id),
|
||||
has_default: p.default.is_some(),
|
||||
object_lifetime_default:
|
||||
object_lifetime_defaults.map_or(rl::Set1::Empty, |o| o[i]),
|
||||
pure_wrt_drop: p.pure_wrt_drop,
|
||||
}
|
||||
});
|
||||
let mut types: Vec<_> = opt_self.into_iter().chain(types).collect();
|
||||
|
||||
|
|
@ -1476,19 +1516,25 @@ fn generics_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||
index: type_start + i as u32,
|
||||
name: Symbol::intern("<upvar>"),
|
||||
def_id: def_id,
|
||||
default_def_id: parent_def_id.unwrap(),
|
||||
default: None,
|
||||
has_default: false,
|
||||
object_lifetime_default: rl::Set1::Empty,
|
||||
pure_wrt_drop: false,
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
let mut type_param_to_index = BTreeMap::new();
|
||||
for param in &types {
|
||||
type_param_to_index.insert(param.def_id.index, param.index);
|
||||
}
|
||||
|
||||
tcx.alloc_generics(ty::Generics {
|
||||
parent: parent_def_id,
|
||||
parent_regions: parent_regions,
|
||||
parent_types: parent_types,
|
||||
regions: regions,
|
||||
types: types,
|
||||
type_param_to_index: type_param_to_index,
|
||||
has_self: has_self || parent_has_self
|
||||
})
|
||||
})
|
||||
|
|
@ -1576,6 +1622,9 @@ fn type_of_def_id<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||
|def, _| ccx.tcx.mk_param_from_def(def)
|
||||
))
|
||||
}
|
||||
NodeTyParam(&hir::TyParam { default: Some(ref ty), .. }) => {
|
||||
ccx.icx(&()).to_ty(ty)
|
||||
}
|
||||
x => {
|
||||
bug!("unexpected sort of node in type_of_def_id(): {:?}", x);
|
||||
}
|
||||
|
|
@ -1808,54 +1857,6 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
|
|||
}
|
||||
}
|
||||
|
||||
fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
|
||||
index: u32,
|
||||
param: &hir::TyParam,
|
||||
allow_defaults: bool)
|
||||
-> ty::TypeParameterDef<'tcx>
|
||||
{
|
||||
let tcx = ccx.tcx;
|
||||
match tcx.ty_param_defs.borrow().get(¶m.id) {
|
||||
Some(d) => { return d.clone(); }
|
||||
None => { }
|
||||
}
|
||||
|
||||
let default =
|
||||
param.default.as_ref().map(|def| ccx.icx(&()).to_ty(def));
|
||||
|
||||
let parent = tcx.hir.get_parent(param.id);
|
||||
|
||||
if !allow_defaults && default.is_some() {
|
||||
if !tcx.sess.features.borrow().default_type_parameter_fallback {
|
||||
tcx.sess.add_lint(
|
||||
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
|
||||
param.id,
|
||||
param.span,
|
||||
format!("defaults for type parameters are only allowed in `struct`, \
|
||||
`enum`, `type`, or `trait` definitions."));
|
||||
}
|
||||
}
|
||||
|
||||
let def = ty::TypeParameterDef {
|
||||
index: index,
|
||||
name: param.name,
|
||||
def_id: ccx.tcx.hir.local_def_id(param.id),
|
||||
default_def_id: ccx.tcx.hir.local_def_id(parent),
|
||||
default: default,
|
||||
pure_wrt_drop: param.pure_wrt_drop,
|
||||
};
|
||||
|
||||
if def.name == keywords::SelfType.name() {
|
||||
span_bug!(param.span, "`Self` should not be the name of a regular parameter");
|
||||
}
|
||||
|
||||
tcx.ty_param_defs.borrow_mut().insert(param.id, def.clone());
|
||||
|
||||
debug!("get_or_create_type_parameter_def: def for type param: {:?}", def);
|
||||
|
||||
def
|
||||
}
|
||||
|
||||
pub enum SizedByDefault { Yes, No, }
|
||||
|
||||
/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
|
||||
|
|
|
|||
|
|
@ -1701,33 +1701,6 @@ struct Foo {
|
|||
```
|
||||
"##,
|
||||
|
||||
E0128: r##"
|
||||
Type parameter defaults can only use parameters that occur before them.
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0128
|
||||
struct Foo<T=U, U=()> {
|
||||
field1: T,
|
||||
filed2: U,
|
||||
}
|
||||
// error: type parameters with a default cannot use forward declared
|
||||
// identifiers
|
||||
```
|
||||
|
||||
Since type parameters are evaluated in-order, you may be able to fix this issue
|
||||
by doing:
|
||||
|
||||
```
|
||||
struct Foo<U=(), T=U> {
|
||||
field1: T,
|
||||
filed2: U,
|
||||
}
|
||||
```
|
||||
|
||||
Please also verify that this wasn't because of a name-clash and rename the type
|
||||
parameter if so.
|
||||
"##,
|
||||
|
||||
E0131: r##"
|
||||
It is not possible to define `main` with type parameters, or even with function
|
||||
parameters. When `main` is present, it must take no arguments and return `()`.
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ use util::common::time;
|
|||
|
||||
use syntax::ast;
|
||||
use syntax::abi::Abi;
|
||||
use syntax::symbol::keywords;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use std::iter;
|
||||
|
|
@ -193,6 +194,30 @@ fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
|||
})
|
||||
}
|
||||
|
||||
fn ty_param_owner(tcx: TyCtxt, id: ast::NodeId) -> ast::NodeId {
|
||||
match tcx.hir.get(id) {
|
||||
hir::map::NodeItem(&hir::Item { node: hir::ItemTrait(..), .. }) => id,
|
||||
hir::map::NodeTyParam(_) => tcx.hir.get_parent_node(id),
|
||||
_ => {
|
||||
bug!("ty_param_owner: {} not a type parameter",
|
||||
tcx.hir.node_to_string(id))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_param_name(tcx: TyCtxt, id: ast::NodeId) -> ast::Name {
|
||||
match tcx.hir.get(id) {
|
||||
hir::map::NodeItem(&hir::Item { node: hir::ItemTrait(..), .. }) => {
|
||||
keywords::SelfType.name()
|
||||
}
|
||||
hir::map::NodeTyParam(tp) => tp.name,
|
||||
_ => {
|
||||
bug!("ty_param_name: {} not a type parameter",
|
||||
tcx.hir.node_to_string(id))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_main_fn_ty(ccx: &CrateCtxt,
|
||||
main_id: ast::NodeId,
|
||||
main_span: Span) {
|
||||
|
|
|
|||
|
|
@ -279,7 +279,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn add_constraints_from_trait_ref(&mut self,
|
||||
generics: &ty::Generics<'tcx>,
|
||||
generics: &ty::Generics,
|
||||
trait_ref: ty::TraitRef<'tcx>,
|
||||
variance: VarianceTermPtr<'a>) {
|
||||
debug!("add_constraints_from_trait_ref: trait_ref={:?} variance={:?}",
|
||||
|
|
@ -305,7 +305,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
|||
/// in a context with the generics defined in `generics` and
|
||||
/// ambient variance `variance`
|
||||
fn add_constraints_from_ty(&mut self,
|
||||
generics: &ty::Generics<'tcx>,
|
||||
generics: &ty::Generics,
|
||||
ty: Ty<'tcx>,
|
||||
variance: VarianceTermPtr<'a>) {
|
||||
debug!("add_constraints_from_ty(ty={:?}, variance={:?})",
|
||||
|
|
@ -433,9 +433,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
|||
/// Adds constraints appropriate for a nominal type (enum, struct,
|
||||
/// object, etc) appearing in a context with ambient variance `variance`
|
||||
fn add_constraints_from_substs(&mut self,
|
||||
generics: &ty::Generics<'tcx>,
|
||||
generics: &ty::Generics,
|
||||
def_id: DefId,
|
||||
type_param_defs: &[ty::TypeParameterDef<'tcx>],
|
||||
type_param_defs: &[ty::TypeParameterDef],
|
||||
region_param_defs: &[ty::RegionParameterDef],
|
||||
substs: &Substs<'tcx>,
|
||||
variance: VarianceTermPtr<'a>) {
|
||||
|
|
@ -465,7 +465,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
|||
/// Adds constraints appropriate for a function with signature
|
||||
/// `sig` appearing in a context with ambient variance `variance`
|
||||
fn add_constraints_from_sig(&mut self,
|
||||
generics: &ty::Generics<'tcx>,
|
||||
generics: &ty::Generics,
|
||||
sig: &ty::PolyFnSig<'tcx>,
|
||||
variance: VarianceTermPtr<'a>) {
|
||||
let contra = self.contravariant(variance);
|
||||
|
|
@ -478,7 +478,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
|||
/// Adds constraints appropriate for a region appearing in a
|
||||
/// context with ambient variance `variance`
|
||||
fn add_constraints_from_region(&mut self,
|
||||
generics: &ty::Generics<'tcx>,
|
||||
generics: &ty::Generics,
|
||||
region: &'tcx ty::Region,
|
||||
variance: VarianceTermPtr<'a>) {
|
||||
match *region {
|
||||
|
|
@ -518,7 +518,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
|
|||
/// Adds constraints appropriate for a mutability-type pair
|
||||
/// appearing in a context with ambient variance `variance`
|
||||
fn add_constraints_from_mt(&mut self,
|
||||
generics: &ty::Generics<'tcx>,
|
||||
generics: &ty::Generics,
|
||||
mt: &ty::TypeAndMut<'tcx>,
|
||||
variance: VarianceTermPtr<'a>) {
|
||||
match mt.mutbl {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue