Auto merge of #48523 - varkor:generics-ty-generalisations, r=nikomatsakis
The Great Generics Generalisation: Ty Edition Part of the generic parameter refactoring effort, split off from https://github.com/rust-lang/rust/pull/48149. Contains the `ty`-relative refactoring. r? @eddyb
This commit is contained in:
commit
e44fc6c52d
48 changed files with 985 additions and 825 deletions
|
@ -1459,10 +1459,9 @@ impl<'a> LoweringContext<'a> {
|
|||
return n;
|
||||
}
|
||||
assert!(!def_id.is_local());
|
||||
let n = self.cstore
|
||||
.item_generics_cloned_untracked(def_id, self.sess)
|
||||
.regions
|
||||
.len();
|
||||
let item_generics =
|
||||
self.cstore.item_generics_cloned_untracked(def_id, self.sess);
|
||||
let n = item_generics.own_counts().lifetimes;
|
||||
self.type_def_lifetime_params.insert(def_id, n);
|
||||
n
|
||||
});
|
||||
|
|
|
@ -735,54 +735,40 @@ impl<'a> HashStable<StableHashingContext<'a>> for ty::Generics {
|
|||
hasher: &mut StableHasher<W>) {
|
||||
let ty::Generics {
|
||||
parent,
|
||||
parent_regions,
|
||||
parent_types,
|
||||
ref regions,
|
||||
ref types,
|
||||
ref parent_count,
|
||||
ref params,
|
||||
|
||||
// Reverse map to each `TypeParameterDef`'s `index` field, from
|
||||
// Reverse map to each `TypeParamDef`'s `index` field, from
|
||||
// `def_id.index` (`def_id.krate` is the same as the item's).
|
||||
type_param_to_index: _, // Don't hash this
|
||||
param_def_id_to_index: _, // Don't hash this
|
||||
has_self,
|
||||
has_late_bound_regions,
|
||||
} = *self;
|
||||
|
||||
parent.hash_stable(hcx, hasher);
|
||||
parent_regions.hash_stable(hcx, hasher);
|
||||
parent_types.hash_stable(hcx, hasher);
|
||||
regions.hash_stable(hcx, hasher);
|
||||
types.hash_stable(hcx, hasher);
|
||||
parent_count.hash_stable(hcx, hasher);
|
||||
params.hash_stable(hcx, hasher);
|
||||
has_self.hash_stable(hcx, hasher);
|
||||
has_late_bound_regions.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> HashStable<StableHashingContext<'a>>
|
||||
for ty::RegionParameterDef {
|
||||
fn hash_stable<W: StableHasherResult>(&self,
|
||||
hcx: &mut StableHashingContext<'a>,
|
||||
hasher: &mut StableHasher<W>) {
|
||||
let ty::RegionParameterDef {
|
||||
name,
|
||||
def_id,
|
||||
index,
|
||||
pure_wrt_drop
|
||||
} = *self;
|
||||
impl_stable_hash_for!(enum ty::GenericParamDefKind {
|
||||
Lifetime,
|
||||
Type(ty)
|
||||
});
|
||||
|
||||
name.hash_stable(hcx, hasher);
|
||||
def_id.hash_stable(hcx, hasher);
|
||||
index.hash_stable(hcx, hasher);
|
||||
pure_wrt_drop.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
impl_stable_hash_for!(struct ty::TypeParameterDef {
|
||||
impl_stable_hash_for!(struct ty::GenericParamDef {
|
||||
name,
|
||||
def_id,
|
||||
index,
|
||||
pure_wrt_drop,
|
||||
kind
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(struct ty::TypeParamDef {
|
||||
has_default,
|
||||
object_lifetime_default,
|
||||
pure_wrt_drop,
|
||||
synthetic
|
||||
});
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ use infer::outlives::free_region_map::FreeRegionRelations;
|
|||
use rustc_data_structures::fx::FxHashMap;
|
||||
use syntax::ast;
|
||||
use traits::{self, PredicateObligation};
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
use ty::{self, Ty, TyCtxt, GenericParamDefKind};
|
||||
use ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder};
|
||||
use ty::outlives::Component;
|
||||
use ty::subst::{Kind, Substs, UnpackedKind};
|
||||
|
@ -313,12 +313,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
// `['a]` for the first impl trait and `'b` for the
|
||||
// second.
|
||||
let mut least_region = None;
|
||||
for region_def in &abstract_type_generics.regions {
|
||||
// Find the index of this region in the list of substitutions.
|
||||
let index = region_def.index as usize;
|
||||
|
||||
for param in &abstract_type_generics.params {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {}
|
||||
_ => continue
|
||||
}
|
||||
// Get the value supplied for this region from the substs.
|
||||
let subst_arg = anon_defn.substs.region_at(index);
|
||||
let subst_arg = anon_defn.substs.region_at(param.index as usize);
|
||||
|
||||
// Compute the least upper bound of it with the other regions.
|
||||
debug!("constrain_anon_types: least_region={:?}", least_region);
|
||||
|
@ -616,10 +617,9 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ReverseMapper<'cx, 'gcx, 'tcx>
|
|||
// during trans.
|
||||
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
let parent_len = generics.parent_count();
|
||||
let substs = self.tcx.mk_substs(substs.substs.iter().enumerate().map(
|
||||
|(index, &kind)| {
|
||||
if index < parent_len {
|
||||
if index < generics.parent_count {
|
||||
// Accommodate missing regions in the parent kinds...
|
||||
self.fold_kind_mapping_missing_regions_to_empty(kind)
|
||||
} else {
|
||||
|
|
|
@ -21,9 +21,9 @@ use hir::def_id::DefId;
|
|||
use middle::free_region::RegionRelations;
|
||||
use middle::region;
|
||||
use middle::lang_items;
|
||||
use ty::subst::Substs;
|
||||
use ty::subst::{Kind, Substs};
|
||||
use ty::{TyVid, IntVid, FloatVid};
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
use ty::{self, Ty, TyCtxt, GenericParamDefKind};
|
||||
use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
|
||||
use ty::fold::TypeFoldable;
|
||||
use ty::relate::RelateResult;
|
||||
|
@ -905,34 +905,35 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
self.next_region_var(RegionVariableOrigin::NLL(origin))
|
||||
}
|
||||
|
||||
/// Create a region inference variable for the given
|
||||
/// region parameter definition.
|
||||
pub fn region_var_for_def(&self,
|
||||
span: Span,
|
||||
def: &ty::RegionParameterDef)
|
||||
-> ty::Region<'tcx> {
|
||||
self.next_region_var(EarlyBoundRegion(span, def.name))
|
||||
}
|
||||
pub fn var_for_def(&self,
|
||||
span: Span,
|
||||
param: &ty::GenericParamDef)
|
||||
-> Kind<'tcx> {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
// Create a region inference variable for the given
|
||||
// region parameter definition.
|
||||
self.next_region_var(EarlyBoundRegion(span, param.name)).into()
|
||||
}
|
||||
GenericParamDefKind::Type(_) => {
|
||||
// Create a type inference variable for the given
|
||||
// type parameter definition. The substitutions are
|
||||
// for actual parameters that may be referred to by
|
||||
// the default of this type parameter, if it exists.
|
||||
// E.g. `struct Foo<A, B, C = (A, B)>(...);` when
|
||||
// used in a path such as `Foo::<T, U>::new()` will
|
||||
// use an inference variable for `C` with `[T, U]`
|
||||
// as the substitutions for the default, `(T, U)`.
|
||||
let ty_var_id =
|
||||
self.type_variables
|
||||
.borrow_mut()
|
||||
.new_var(self.universe(),
|
||||
false,
|
||||
TypeVariableOrigin::TypeParameterDefinition(span, param.name));
|
||||
|
||||
/// Create a type inference variable for the given
|
||||
/// type parameter definition. The substitutions are
|
||||
/// for actual parameters that may be referred to by
|
||||
/// the default of this type parameter, if it exists.
|
||||
/// E.g. `struct Foo<A, B, C = (A, B)>(...);` when
|
||||
/// used in a path such as `Foo::<T, U>::new()` will
|
||||
/// use an inference variable for `C` with `[T, U]`
|
||||
/// as the substitutions for the default, `(T, U)`.
|
||||
pub fn type_var_for_def(&self,
|
||||
span: Span,
|
||||
def: &ty::TypeParameterDef)
|
||||
-> Ty<'tcx> {
|
||||
let ty_var_id = self.type_variables
|
||||
.borrow_mut()
|
||||
.new_var(self.universe(),
|
||||
false,
|
||||
TypeVariableOrigin::TypeParameterDefinition(span, def.name));
|
||||
|
||||
self.tcx.mk_var(ty_var_id)
|
||||
self.tcx.mk_var(ty_var_id).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a set of generics defined on a type or impl, returns a substitution mapping each
|
||||
|
@ -941,10 +942,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
span: Span,
|
||||
def_id: DefId)
|
||||
-> &'tcx Substs<'tcx> {
|
||||
Substs::for_item(self.tcx, def_id, |def, _| {
|
||||
self.region_var_for_def(span, def)
|
||||
}, |def, _| {
|
||||
self.type_var_for_def(span, def)
|
||||
Substs::for_item(self.tcx, def_id, |param, _| {
|
||||
self.var_for_def(span, param)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#![cfg_attr(stage0, feature(dyn_trait))]
|
||||
#![feature(from_ref)]
|
||||
#![feature(fs_read_write)]
|
||||
#![feature(iterator_find_map)]
|
||||
#![cfg_attr(windows, feature(libc))]
|
||||
#![cfg_attr(stage0, feature(macro_lifetime_matcher))]
|
||||
#![feature(macro_vis_matcher)]
|
||||
|
|
|
@ -20,7 +20,7 @@ use hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
|
|||
use hir::map::Map;
|
||||
use hir::ItemLocalId;
|
||||
use hir::LifetimeName;
|
||||
use ty::{self, TyCtxt};
|
||||
use ty::{self, TyCtxt, GenericParamDefKind};
|
||||
|
||||
use errors::DiagnosticBuilder;
|
||||
use rustc::lint;
|
||||
|
@ -667,8 +667,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
|||
for lt_def in generics.lifetimes() {
|
||||
let (lt_name, region) = Region::early(&self.tcx.hir, &mut index, <_def);
|
||||
if let hir::LifetimeName::Underscore = lt_name {
|
||||
// Pick the elided lifetime "definition" if one exists and use it to make an
|
||||
// elision scope.
|
||||
// Pick the elided lifetime "definition" if one exists and use it to make
|
||||
// an elision scope.
|
||||
elision = Some(region);
|
||||
} else {
|
||||
lifetimes.insert(lt_name, region);
|
||||
|
@ -1659,9 +1659,16 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||
.entry(def_id)
|
||||
.or_insert_with(|| {
|
||||
tcx.generics_of(def_id)
|
||||
.types
|
||||
.params
|
||||
.iter()
|
||||
.map(|def| def.object_lifetime_default)
|
||||
.filter_map(|param| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Type(ty) => {
|
||||
Some(ty.object_lifetime_default)
|
||||
}
|
||||
GenericParamDefKind::Lifetime => None,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
};
|
||||
|
|
|
@ -222,9 +222,14 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
|
|||
});
|
||||
|
||||
let names_map: FxHashSet<String> = generics
|
||||
.regions
|
||||
.params
|
||||
.iter()
|
||||
.map(|l| l.name.to_string())
|
||||
.filter_map(|param| {
|
||||
match param.kind {
|
||||
ty::GenericParamDefKind::Lifetime => Some(param.name.to_string()),
|
||||
_ => None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let body_ids: FxHashSet<_> = infcx
|
||||
|
|
|
@ -36,6 +36,7 @@ use std::fmt;
|
|||
use syntax::ast;
|
||||
use session::DiagnosticMessageId;
|
||||
use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
|
||||
use ty::GenericParamDefKind;
|
||||
use ty::error::ExpectedFound;
|
||||
use ty::fast_reject;
|
||||
use ty::fold::TypeFolder;
|
||||
|
@ -378,12 +379,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
|||
flags.push(("_Self".to_string(), Some(self.tcx.type_of(def.did).to_string())));
|
||||
}
|
||||
|
||||
for param in generics.types.iter() {
|
||||
for param in generics.params.iter() {
|
||||
let value = match param.kind {
|
||||
GenericParamDefKind::Type(_) => {
|
||||
trait_ref.substs[param.index as usize].to_string()
|
||||
},
|
||||
GenericParamDefKind::Lifetime => continue,
|
||||
};
|
||||
let name = param.name.to_string();
|
||||
let ty = trait_ref.substs.type_for_def(param);
|
||||
let ty_str = ty.to_string();
|
||||
flags.push((name.clone(),
|
||||
Some(ty_str.clone())));
|
||||
flags.push((name, Some(value)));
|
||||
}
|
||||
|
||||
if let Some(true) = self_ty.ty_to_def_id().map(|def_id| def_id.is_local()) {
|
||||
|
|
|
@ -23,7 +23,7 @@ use infer::outlives::env::OutlivesEnvironment;
|
|||
use middle::region;
|
||||
use middle::const_val::ConstEvalErr;
|
||||
use ty::subst::Substs;
|
||||
use ty::{self, AdtKind, Slice, Ty, TyCtxt, TypeFoldable, ToPredicate};
|
||||
use ty::{self, AdtKind, Slice, Ty, TyCtxt, GenericParamDefKind, TypeFoldable, ToPredicate};
|
||||
use ty::error::{ExpectedFound, TypeError};
|
||||
use infer::{InferCtxt};
|
||||
|
||||
|
@ -841,10 +841,14 @@ fn vtable_methods<'a, 'tcx>(
|
|||
// the method may have some early-bound lifetimes, add
|
||||
// regions for those
|
||||
let substs = trait_ref.map_bound(|trait_ref| {
|
||||
Substs::for_item(
|
||||
tcx, def_id,
|
||||
|_, _| tcx.types.re_erased,
|
||||
|def, _| trait_ref.substs.type_for_def(def))
|
||||
Substs::for_item(tcx, def_id, |param, _| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => tcx.types.re_erased.into(),
|
||||
GenericParamDefKind::Type(_) => {
|
||||
trait_ref.substs[param.index as usize]
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// the trait type may have higher-ranked lifetimes in it;
|
||||
|
|
|
@ -284,7 +284,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
// We can't monomorphize things like `fn foo<A>(...)`.
|
||||
if !self.generics_of(method.def_id).types.is_empty() {
|
||||
if self.generics_of(method.def_id).own_counts().types != 0 {
|
||||
return Some(MethodViolationCode::Generic);
|
||||
}
|
||||
|
||||
|
@ -387,7 +387,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
pub(super) fn is_object_safe_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
trait_def_id: DefId)
|
||||
-> bool {
|
||||
trait_def_id: DefId) -> bool {
|
||||
tcx.object_safety_violations(trait_def_id).is_empty()
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
use fmt_macros::{Parser, Piece, Position};
|
||||
|
||||
use hir::def_id::DefId;
|
||||
use ty::{self, TyCtxt};
|
||||
use ty::{self, TyCtxt, GenericParamDefKind};
|
||||
use util::common::ErrorReported;
|
||||
use util::nodemap::FxHashMap;
|
||||
|
||||
|
@ -243,7 +243,6 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
|
|||
let name = tcx.item_name(trait_def_id);
|
||||
let generics = tcx.generics_of(trait_def_id);
|
||||
let parser = Parser::new(&self.0);
|
||||
let types = &generics.types;
|
||||
let mut result = Ok(());
|
||||
for token in parser {
|
||||
match token {
|
||||
|
@ -254,13 +253,13 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
|
|||
// `{ThisTraitsName}` is allowed
|
||||
Position::ArgumentNamed(s) if s == name => (),
|
||||
// So is `{A}` if A is a type parameter
|
||||
Position::ArgumentNamed(s) => match types.iter().find(|t| {
|
||||
t.name == s
|
||||
Position::ArgumentNamed(s) => match generics.params.iter().find(|param| {
|
||||
param.name == s
|
||||
}) {
|
||||
Some(_) => (),
|
||||
None => {
|
||||
span_err!(tcx.sess, span, E0230,
|
||||
"there is no type parameter \
|
||||
"there is no parameter \
|
||||
{} on trait {}",
|
||||
s, name);
|
||||
result = Err(ErrorReported);
|
||||
|
@ -288,9 +287,15 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString {
|
|||
let name = tcx.item_name(trait_ref.def_id);
|
||||
let trait_str = tcx.item_path_str(trait_ref.def_id);
|
||||
let generics = tcx.generics_of(trait_ref.def_id);
|
||||
let generic_map = generics.types.iter().map(|param| {
|
||||
(param.name.to_string(),
|
||||
trait_ref.substs.type_for_def(param).to_string())
|
||||
let generic_map = generics.params.iter().filter_map(|param| {
|
||||
let value = match param.kind {
|
||||
GenericParamDefKind::Type(_) => {
|
||||
trait_ref.substs[param.index as usize].to_string()
|
||||
},
|
||||
GenericParamDefKind::Lifetime => return None
|
||||
};
|
||||
let name = param.name.to_string();
|
||||
Some((name, value))
|
||||
}).collect::<FxHashMap<String, String>>();
|
||||
|
||||
let parser = Parser::new(&self.0);
|
||||
|
|
|
@ -213,7 +213,7 @@ impl<'cx, 'gcx, 'tcx> Elaborator<'cx, 'gcx, 'tcx> {
|
|||
},
|
||||
|
||||
Component::Param(p) => {
|
||||
let ty = tcx.mk_param(p.idx, p.name);
|
||||
let ty = tcx.mk_ty_param(p.idx, p.name);
|
||||
Some(ty::Predicate::TypeOutlives(
|
||||
ty::Binder::dummy(ty::OutlivesPredicate(ty, r_min))))
|
||||
},
|
||||
|
|
|
@ -44,6 +44,7 @@ use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predic
|
|||
use ty::RegionKind;
|
||||
use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
|
||||
use ty::TypeVariants::*;
|
||||
use ty::GenericParamDefKind;
|
||||
use ty::layout::{LayoutDetails, TargetDataLayout};
|
||||
use ty::maps;
|
||||
use ty::steal::Steal;
|
||||
|
@ -2325,15 +2326,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> {
|
||||
let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem);
|
||||
let adt_def = self.adt_def(def_id);
|
||||
let generics = self.generics_of(def_id);
|
||||
let mut substs = vec![Kind::from(ty)];
|
||||
// Add defaults for other generic params if there are some.
|
||||
for def in generics.types.iter().skip(1) {
|
||||
assert!(def.has_default);
|
||||
let ty = self.type_of(def.def_id).subst(self, &substs);
|
||||
substs.push(ty.into());
|
||||
}
|
||||
let substs = self.mk_substs(substs.into_iter());
|
||||
let substs = Substs::for_item(self, def_id, |param, substs| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => bug!(),
|
||||
GenericParamDefKind::Type(ty_param) => {
|
||||
if param.index == 0 {
|
||||
ty.into()
|
||||
} else {
|
||||
assert!(ty_param.has_default);
|
||||
self.type_of(param.def_id).subst(self, substs).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
self.mk_ty(TyAdt(adt_def, substs))
|
||||
}
|
||||
|
||||
|
@ -2457,18 +2462,23 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
self.mk_ty(TyInfer(it))
|
||||
}
|
||||
|
||||
pub fn mk_param(self,
|
||||
pub fn mk_ty_param(self,
|
||||
index: u32,
|
||||
name: InternedString) -> Ty<'tcx> {
|
||||
self.mk_ty(TyParam(ParamTy { idx: index, name: name }))
|
||||
}
|
||||
|
||||
pub fn mk_self_type(self) -> Ty<'tcx> {
|
||||
self.mk_param(0, keywords::SelfType.name().as_interned_str())
|
||||
self.mk_ty_param(0, keywords::SelfType.name().as_interned_str())
|
||||
}
|
||||
|
||||
pub fn mk_param_from_def(self, def: &ty::TypeParameterDef) -> Ty<'tcx> {
|
||||
self.mk_param(def.index, def.name)
|
||||
pub fn mk_param_from_def(self, param: &ty::GenericParamDef) -> Kind<'tcx> {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
self.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())).into()
|
||||
}
|
||||
GenericParamDefKind::Type(_) => self.mk_ty_param(param.index, param.name).into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mk_anon(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
|
||||
|
|
|
@ -543,7 +543,7 @@ impl<'tcx> QueryDescription<'tcx> for queries::named_region_map<'tcx> {
|
|||
|
||||
impl<'tcx> QueryDescription<'tcx> for queries::is_late_bound_map<'tcx> {
|
||||
fn describe(_tcx: TyCtxt, _: DefIndex) -> String {
|
||||
format!("testing if a region is late boudn")
|
||||
format!("testing if a region is late bound")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -709,148 +709,152 @@ pub enum IntVarValue {
|
|||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub struct FloatVarValue(pub ast::FloatTy);
|
||||
|
||||
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
|
||||
pub struct TypeParameterDef {
|
||||
pub name: InternedString,
|
||||
pub def_id: DefId,
|
||||
pub index: u32,
|
||||
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct TypeParamDef {
|
||||
pub has_default: bool,
|
||||
pub object_lifetime_default: ObjectLifetimeDefault,
|
||||
|
||||
/// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute
|
||||
/// on generic parameter `T`, asserts data behind the parameter
|
||||
/// `T` won't be accessed during the parent type's `Drop` impl.
|
||||
pub pure_wrt_drop: bool,
|
||||
|
||||
pub synthetic: Option<hir::SyntheticTyParamKind>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
|
||||
pub struct RegionParameterDef {
|
||||
pub name: InternedString,
|
||||
pub def_id: DefId,
|
||||
pub index: u32,
|
||||
|
||||
/// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute
|
||||
/// on generic parameter `'a`, asserts data of lifetime `'a`
|
||||
/// won't be accessed during the parent type's `Drop` impl.
|
||||
pub pure_wrt_drop: bool,
|
||||
}
|
||||
|
||||
impl RegionParameterDef {
|
||||
pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion {
|
||||
ty::EarlyBoundRegion {
|
||||
def_id: self.def_id,
|
||||
index: self.index,
|
||||
name: self.name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_bound_region(&self) -> ty::BoundRegion {
|
||||
self.to_early_bound_region_data().to_bound_region()
|
||||
}
|
||||
}
|
||||
|
||||
impl ty::EarlyBoundRegion {
|
||||
pub fn to_bound_region(&self) -> ty::BoundRegion {
|
||||
ty::BoundRegion::BrNamed(self.def_id, self.name)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub enum GenericParamDefKind {
|
||||
Lifetime,
|
||||
Type(TypeParamDef),
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||
pub struct GenericParamDef {
|
||||
pub name: InternedString,
|
||||
pub def_id: DefId,
|
||||
pub index: u32,
|
||||
|
||||
/// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute
|
||||
/// on generic parameter `'a`/`T`, asserts data behind the parameter
|
||||
/// `'a`/`T` won't be accessed during the parent type's `Drop` impl.
|
||||
pub pure_wrt_drop: bool,
|
||||
|
||||
pub kind: GenericParamDefKind,
|
||||
}
|
||||
|
||||
impl GenericParamDef {
|
||||
pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion {
|
||||
match self.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
ty::EarlyBoundRegion {
|
||||
def_id: self.def_id,
|
||||
index: self.index,
|
||||
name: self.name,
|
||||
}
|
||||
}
|
||||
_ => bug!("cannot convert a non-lifetime parameter def to an early bound region")
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_bound_region(&self) -> ty::BoundRegion {
|
||||
match self.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
self.to_early_bound_region_data().to_bound_region()
|
||||
}
|
||||
_ => bug!("cannot convert a non-lifetime parameter def to an early bound region")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GenericParamCount {
|
||||
pub lifetimes: usize,
|
||||
pub types: usize,
|
||||
}
|
||||
|
||||
/// Information about the formal type/lifetime parameters associated
|
||||
/// with an item or method. Analogous to hir::Generics.
|
||||
///
|
||||
/// Note that in the presence of a `Self` parameter, the ordering here
|
||||
/// is different from the ordering in a Substs. Substs are ordered as
|
||||
/// Self, *Regions, *Other Type Params, (...child generics)
|
||||
/// while this struct is ordered as
|
||||
/// regions = Regions
|
||||
/// types = [Self, *Other Type Params]
|
||||
/// The ordering of parameters is the same as in Subst (excluding child generics):
|
||||
/// Self (optionally), Lifetime params..., Type params...
|
||||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct Generics {
|
||||
pub parent: Option<DefId>,
|
||||
pub parent_regions: u32,
|
||||
pub parent_types: u32,
|
||||
pub regions: Vec<RegionParameterDef>,
|
||||
pub types: Vec<TypeParameterDef>,
|
||||
pub parent_count: usize,
|
||||
pub params: Vec<GenericParamDef>,
|
||||
|
||||
/// Reverse map to each `TypeParameterDef`'s `index` field
|
||||
pub type_param_to_index: FxHashMap<DefId, u32>,
|
||||
/// Reverse map to the `index` field of each `GenericParamDef`
|
||||
pub param_def_id_to_index: FxHashMap<DefId, u32>,
|
||||
|
||||
pub has_self: bool,
|
||||
pub has_late_bound_regions: Option<Span>,
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Generics {
|
||||
pub fn parent_count(&self) -> usize {
|
||||
self.parent_regions as usize + self.parent_types as usize
|
||||
}
|
||||
|
||||
pub fn own_count(&self) -> usize {
|
||||
self.regions.len() + self.types.len()
|
||||
}
|
||||
|
||||
pub fn count(&self) -> usize {
|
||||
self.parent_count() + self.own_count()
|
||||
self.parent_count + self.params.len()
|
||||
}
|
||||
|
||||
pub fn own_counts(&self) -> GenericParamCount {
|
||||
// We could cache this as a property of `GenericParamCount`, but
|
||||
// the aim is to refactor this away entirely eventually and the
|
||||
// presence of this method will be a constant reminder.
|
||||
let mut own_counts = GenericParamCount {
|
||||
lifetimes: 0,
|
||||
types: 0,
|
||||
};
|
||||
|
||||
for param in &self.params {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => own_counts.lifetimes += 1,
|
||||
GenericParamDefKind::Type(_) => own_counts.types += 1,
|
||||
};
|
||||
}
|
||||
|
||||
own_counts
|
||||
}
|
||||
|
||||
pub fn requires_monomorphization(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
|
||||
for param in &self.params {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Type(_) => return true,
|
||||
GenericParamDefKind::Lifetime => {}
|
||||
}
|
||||
}
|
||||
if let Some(parent_def_id) = self.parent {
|
||||
let parent = tcx.generics_of(parent_def_id);
|
||||
parent.requires_monomorphization(tcx)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn region_param(&'tcx self,
|
||||
param: &EarlyBoundRegion,
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>)
|
||||
-> &'tcx RegionParameterDef
|
||||
-> &'tcx GenericParamDef
|
||||
{
|
||||
if let Some(index) = param.index.checked_sub(self.parent_count() as u32) {
|
||||
&self.regions[index as usize - self.has_self as usize]
|
||||
if let Some(index) = param.index.checked_sub(self.parent_count as u32) {
|
||||
let param = &self.params[index as usize];
|
||||
match param.kind {
|
||||
ty::GenericParamDefKind::Lifetime => param,
|
||||
_ => bug!("expected lifetime parameter, but found another generic parameter")
|
||||
}
|
||||
} else {
|
||||
tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
|
||||
.region_param(param, tcx)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `TypeParameterDef` associated with this `ParamTy`.
|
||||
/// Returns the `TypeParamDef` associated with this `ParamTy`.
|
||||
pub fn type_param(&'tcx self,
|
||||
param: &ParamTy,
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>)
|
||||
-> &TypeParameterDef {
|
||||
if let Some(idx) = param.idx.checked_sub(self.parent_count() as u32) {
|
||||
// non-Self type parameters are always offset by exactly
|
||||
// `self.regions.len()`. In the absence of a Self, this is obvious,
|
||||
// but even in the presence of a `Self` we just have to "compensate"
|
||||
// for the regions:
|
||||
//
|
||||
// Without a `Self` (or in a nested generics that doesn't have
|
||||
// a `Self` in itself, even through it parent does), for example
|
||||
// for `fn foo<'a, T1, T2>()`, the situation is:
|
||||
// Substs:
|
||||
// 0 1 2
|
||||
// 'a T1 T2
|
||||
// generics.types:
|
||||
// 0 1
|
||||
// T1 T2
|
||||
//
|
||||
// And with a `Self`, for example for `trait Foo<'a, 'b, T1, T2>`, the
|
||||
// situation is:
|
||||
// Substs:
|
||||
// 0 1 2 3 4
|
||||
// Self 'a 'b T1 T2
|
||||
// generics.types:
|
||||
// 0 1 2
|
||||
// Self T1 T2
|
||||
//
|
||||
// And it can be seen that in both cases, to move from a substs
|
||||
// offset to a generics offset you just have to offset by the
|
||||
// number of regions.
|
||||
let type_param_offset = self.regions.len();
|
||||
|
||||
let has_self = self.has_self && self.parent.is_none();
|
||||
let is_separated_self = type_param_offset != 0 && idx == 0 && has_self;
|
||||
|
||||
if let Some(idx) = (idx as usize).checked_sub(type_param_offset) {
|
||||
assert!(!is_separated_self, "found a Self after type_param_offset");
|
||||
&self.types[idx]
|
||||
} else {
|
||||
assert!(is_separated_self, "non-Self param before type_param_offset");
|
||||
&self.types[0]
|
||||
-> &'tcx GenericParamDef {
|
||||
if let Some(index) = param.idx.checked_sub(self.parent_count as u32) {
|
||||
let param = &self.params[index as usize];
|
||||
match param.kind {
|
||||
ty::GenericParamDefKind::Type(_) => param,
|
||||
_ => bug!("expected type parameter, but found another generic parameter")
|
||||
}
|
||||
} else {
|
||||
tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
|
||||
|
|
|
@ -292,7 +292,7 @@ impl<'tcx> ClosureSubsts<'tcx> {
|
|||
/// ordering.
|
||||
fn split(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> SplitClosureSubsts<'tcx> {
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let parent_len = generics.parent_count();
|
||||
let parent_len = generics.parent_count;
|
||||
SplitClosureSubsts {
|
||||
closure_kind_ty: self.substs.type_at(parent_len),
|
||||
closure_sig_ty: self.substs.type_at(parent_len + 1),
|
||||
|
@ -366,7 +366,7 @@ struct SplitGeneratorSubsts<'tcx> {
|
|||
impl<'tcx> GeneratorSubsts<'tcx> {
|
||||
fn split(self, def_id: DefId, tcx: TyCtxt<'_, '_, '_>) -> SplitGeneratorSubsts<'tcx> {
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let parent_len = generics.parent_count();
|
||||
let parent_len = generics.parent_count;
|
||||
SplitGeneratorSubsts {
|
||||
yield_ty: self.substs.type_at(parent_len),
|
||||
return_ty: self.substs.type_at(parent_len + 1),
|
||||
|
@ -928,12 +928,12 @@ impl<'a, 'gcx, 'tcx> ParamTy {
|
|||
ParamTy::new(0, keywords::SelfType.name().as_interned_str())
|
||||
}
|
||||
|
||||
pub fn for_def(def: &ty::TypeParameterDef) -> ParamTy {
|
||||
pub fn for_def(def: &ty::GenericParamDef) -> ParamTy {
|
||||
ParamTy::new(def.index, def.name)
|
||||
}
|
||||
|
||||
pub fn to_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
|
||||
tcx.mk_param(self.idx, self.name)
|
||||
tcx.mk_ty_param(self.idx, self.name)
|
||||
}
|
||||
|
||||
pub fn is_self(&self) -> bool {
|
||||
|
|
|
@ -174,92 +174,72 @@ impl<'tcx> Decodable for Kind<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A substitution mapping type/region parameters to new values.
|
||||
/// A substitution mapping generic parameters to new values.
|
||||
pub type Substs<'tcx> = Slice<Kind<'tcx>>;
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Substs<'tcx> {
|
||||
/// Creates a Substs that maps each generic parameter to itself.
|
||||
pub fn identity_for_item(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId)
|
||||
-> &'tcx Substs<'tcx> {
|
||||
Substs::for_item(tcx, def_id, |def, _| {
|
||||
tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data()))
|
||||
}, |def, _| tcx.mk_param_from_def(def))
|
||||
Substs::for_item(tcx, def_id, |param, _| {
|
||||
tcx.mk_param_from_def(param)
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a Substs for generic parameter definitions,
|
||||
/// by calling closures to obtain each region and type.
|
||||
/// by calling closures to obtain each kind.
|
||||
/// The closures get to observe the Substs as they're
|
||||
/// being built, which can be used to correctly
|
||||
/// substitute defaults of type parameters.
|
||||
pub fn for_item<FR, FT>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
mut mk_region: FR,
|
||||
mut mk_type: FT)
|
||||
-> &'tcx Substs<'tcx>
|
||||
where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> ty::Region<'tcx>,
|
||||
FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx> {
|
||||
/// substitute defaults of generic parameters.
|
||||
pub fn for_item<F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
mut mk_kind: F)
|
||||
-> &'tcx Substs<'tcx>
|
||||
where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Kind<'tcx>
|
||||
{
|
||||
let defs = tcx.generics_of(def_id);
|
||||
let mut substs = Vec::with_capacity(defs.count());
|
||||
Substs::fill_item(&mut substs, tcx, defs, &mut mk_region, &mut mk_type);
|
||||
Substs::fill_item(&mut substs, tcx, defs, &mut mk_kind);
|
||||
tcx.intern_substs(&substs)
|
||||
}
|
||||
|
||||
pub fn extend_to<FR, FT>(&self,
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
mut mk_region: FR,
|
||||
mut mk_type: FT)
|
||||
-> &'tcx Substs<'tcx>
|
||||
where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> ty::Region<'tcx>,
|
||||
FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx>
|
||||
pub fn extend_to<F>(&self,
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
def_id: DefId,
|
||||
mut mk_kind: F)
|
||||
-> &'tcx Substs<'tcx>
|
||||
where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Kind<'tcx>
|
||||
{
|
||||
let defs = tcx.generics_of(def_id);
|
||||
let mut result = Vec::with_capacity(defs.count());
|
||||
result.extend(self[..].iter().cloned());
|
||||
Substs::fill_single(&mut result, defs, &mut mk_region, &mut mk_type);
|
||||
Substs::fill_single(&mut result, defs, &mut mk_kind);
|
||||
tcx.intern_substs(&result)
|
||||
}
|
||||
|
||||
pub fn fill_item<FR, FT>(substs: &mut Vec<Kind<'tcx>>,
|
||||
pub fn fill_item<F>(substs: &mut Vec<Kind<'tcx>>,
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
defs: &ty::Generics,
|
||||
mk_region: &mut FR,
|
||||
mk_type: &mut FT)
|
||||
where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> ty::Region<'tcx>,
|
||||
FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx> {
|
||||
mk_kind: &mut F)
|
||||
where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Kind<'tcx>
|
||||
{
|
||||
|
||||
if let Some(def_id) = defs.parent {
|
||||
let parent_defs = tcx.generics_of(def_id);
|
||||
Substs::fill_item(substs, tcx, parent_defs, mk_region, mk_type);
|
||||
Substs::fill_item(substs, tcx, parent_defs, mk_kind);
|
||||
}
|
||||
Substs::fill_single(substs, defs, mk_region, mk_type)
|
||||
Substs::fill_single(substs, defs, mk_kind)
|
||||
}
|
||||
|
||||
fn fill_single<FR, FT>(substs: &mut Vec<Kind<'tcx>>,
|
||||
fn fill_single<F>(substs: &mut Vec<Kind<'tcx>>,
|
||||
defs: &ty::Generics,
|
||||
mk_region: &mut FR,
|
||||
mk_type: &mut FT)
|
||||
where FR: FnMut(&ty::RegionParameterDef, &[Kind<'tcx>]) -> ty::Region<'tcx>,
|
||||
FT: FnMut(&ty::TypeParameterDef, &[Kind<'tcx>]) -> Ty<'tcx> {
|
||||
// Handle Self first, before all regions.
|
||||
let mut types = defs.types.iter();
|
||||
if defs.parent.is_none() && defs.has_self {
|
||||
let def = types.next().unwrap();
|
||||
let ty = mk_type(def, substs);
|
||||
assert_eq!(def.index as usize, substs.len());
|
||||
substs.push(ty.into());
|
||||
}
|
||||
|
||||
for def in &defs.regions {
|
||||
let region = mk_region(def, substs);
|
||||
assert_eq!(def.index as usize, substs.len());
|
||||
substs.push(Kind::from(region));
|
||||
}
|
||||
|
||||
for def in types {
|
||||
let ty = mk_type(def, substs);
|
||||
assert_eq!(def.index as usize, substs.len());
|
||||
substs.push(Kind::from(ty));
|
||||
mk_kind: &mut F)
|
||||
where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Kind<'tcx>
|
||||
{
|
||||
for param in &defs.params {
|
||||
let kind = mk_kind(param, substs);
|
||||
assert_eq!(param.index as usize, substs.len());
|
||||
substs.push(kind);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -308,13 +288,8 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn type_for_def(&self, ty_param_def: &ty::TypeParameterDef) -> Ty<'tcx> {
|
||||
self.type_at(ty_param_def.index as usize)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn region_for_def(&self, def: &ty::RegionParameterDef) -> ty::Region<'tcx> {
|
||||
self.region_at(def.index as usize)
|
||||
pub fn type_for_def(&self, def: &ty::GenericParamDef) -> Kind<'tcx> {
|
||||
self.type_at(def.index as usize).into()
|
||||
}
|
||||
|
||||
/// Transform from substitutions for a child of `source_ancestor`
|
||||
|
@ -327,7 +302,7 @@ impl<'a, 'gcx, 'tcx> Substs<'tcx> {
|
|||
target_substs: &Substs<'tcx>)
|
||||
-> &'tcx Substs<'tcx> {
|
||||
let defs = tcx.generics_of(source_ancestor);
|
||||
tcx.mk_substs(target_substs.iter().chain(&self[defs.own_count()..]).cloned())
|
||||
tcx.mk_substs(target_substs.iter().chain(&self[defs.params.len()..]).cloned())
|
||||
}
|
||||
|
||||
pub fn truncate_to(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, generics: &ty::Generics)
|
||||
|
@ -580,7 +555,7 @@ impl<'a, 'gcx, 'tcx> ty::TraitRef<'tcx> {
|
|||
|
||||
ty::TraitRef {
|
||||
def_id: trait_id,
|
||||
substs: tcx.intern_substs(&substs[..defs.own_count()])
|
||||
substs: tcx.intern_substs(&substs[..defs.params.len()])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,9 +17,9 @@ use hir;
|
|||
use ich::NodeIdHashingMode;
|
||||
use middle::const_val::ConstVal;
|
||||
use traits::{self, ObligationCause};
|
||||
use ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable};
|
||||
use ty::fold::TypeVisitor;
|
||||
use ty::subst::UnpackedKind;
|
||||
use ty::subst::{Substs, UnpackedKind};
|
||||
use ty::maps::TyCtxtAt;
|
||||
use ty::TypeVariants::*;
|
||||
use ty::layout::{Integer, IntegerExt};
|
||||
|
@ -573,11 +573,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
/// Given the def-id of some item that has no type parameters, make
|
||||
/// a suitable "empty substs" for it.
|
||||
pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> &'tcx ty::Substs<'tcx> {
|
||||
ty::Substs::for_item(self, item_def_id,
|
||||
|_, _| self.types.re_erased,
|
||||
|_, _| {
|
||||
bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id)
|
||||
pub fn empty_substs_for_def_id(self, item_def_id: DefId) -> &'tcx Substs<'tcx> {
|
||||
Substs::for_item(self, item_def_id, |param, _| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => self.types.re_erased.into(),
|
||||
GenericParamDefKind::Type(_) => {
|
||||
bug!("empty_substs_for_def_id: {:?} has type parameters", item_def_id)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr};
|
|||
use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple};
|
||||
use ty::{TyClosure, TyGenerator, TyGeneratorWitness, TyForeign, TyProjection, TyAnon};
|
||||
use ty::{TyDynamic, TyInt, TyUint, TyInfer};
|
||||
use ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use ty::{self, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind};
|
||||
use util::nodemap::FxHashSet;
|
||||
|
||||
use std::cell::Cell;
|
||||
|
@ -256,8 +256,10 @@ impl PrintContext {
|
|||
let verbose = self.is_verbose;
|
||||
let mut num_supplied_defaults = 0;
|
||||
let mut has_self = false;
|
||||
let mut num_regions = 0;
|
||||
let mut num_types = 0;
|
||||
let mut own_counts = GenericParamCount {
|
||||
lifetimes: 0,
|
||||
types: 0,
|
||||
};
|
||||
let mut is_value_path = false;
|
||||
let fn_trait_kind = ty::tls::with(|tcx| {
|
||||
// Unfortunately, some kinds of items (e.g., closures) don't have
|
||||
|
@ -303,6 +305,7 @@ impl PrintContext {
|
|||
}
|
||||
}
|
||||
let mut generics = tcx.generics_of(item_def_id);
|
||||
let child_own_counts = generics.own_counts();
|
||||
let mut path_def_id = did;
|
||||
has_self = generics.has_self;
|
||||
|
||||
|
@ -310,10 +313,9 @@ impl PrintContext {
|
|||
if let Some(def_id) = generics.parent {
|
||||
// Methods.
|
||||
assert!(is_value_path);
|
||||
child_types = generics.types.len();
|
||||
child_types = child_own_counts.types;
|
||||
generics = tcx.generics_of(def_id);
|
||||
num_regions = generics.regions.len();
|
||||
num_types = generics.types.len();
|
||||
own_counts = generics.own_counts();
|
||||
|
||||
if has_self {
|
||||
print!(f, self, write("<"), print_display(substs.type_at(0)), write(" as "))?;
|
||||
|
@ -328,20 +330,30 @@ impl PrintContext {
|
|||
assert_eq!(has_self, false);
|
||||
} else {
|
||||
// Types and traits.
|
||||
num_regions = generics.regions.len();
|
||||
num_types = generics.types.len();
|
||||
own_counts = child_own_counts;
|
||||
}
|
||||
}
|
||||
|
||||
if !verbose {
|
||||
if generics.types.last().map_or(false, |def| def.has_default) {
|
||||
let mut type_params =
|
||||
generics.params.iter().rev().filter_map(|param| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Type(ty) => Some((param.def_id, ty.has_default)),
|
||||
GenericParamDefKind::Lifetime => None,
|
||||
}
|
||||
}).peekable();
|
||||
let has_default = {
|
||||
let has_default = type_params.peek().map(|(_, has_default)| has_default);
|
||||
*has_default.unwrap_or(&false)
|
||||
};
|
||||
if has_default {
|
||||
if let Some(substs) = tcx.lift(&substs) {
|
||||
let tps = substs.types().rev().skip(child_types);
|
||||
for (def, actual) in generics.types.iter().rev().zip(tps) {
|
||||
if !def.has_default {
|
||||
let mut types = substs.types().rev().skip(child_types);
|
||||
for ((def_id, has_default), actual) in type_params.zip(types) {
|
||||
if !has_default {
|
||||
break;
|
||||
}
|
||||
if tcx.type_of(def.def_id).subst(tcx, substs) != actual {
|
||||
if tcx.type_of(def_id).subst(tcx, substs) != actual {
|
||||
break;
|
||||
}
|
||||
num_supplied_defaults += 1;
|
||||
|
@ -401,10 +413,11 @@ impl PrintContext {
|
|||
Ok(())
|
||||
};
|
||||
|
||||
print_regions(f, "<", 0, num_regions)?;
|
||||
print_regions(f, "<", 0, own_counts.lifetimes)?;
|
||||
|
||||
let tps = substs.types().take(num_types - num_supplied_defaults)
|
||||
.skip(has_self as usize);
|
||||
let tps = substs.types()
|
||||
.take(own_counts.types - num_supplied_defaults)
|
||||
.skip(has_self as usize);
|
||||
|
||||
for ty in tps {
|
||||
start_or_continue(f, "<", ", ")?;
|
||||
|
@ -435,10 +448,10 @@ impl PrintContext {
|
|||
write!(f, "::{}", item_name)?;
|
||||
}
|
||||
|
||||
print_regions(f, "::<", num_regions, usize::MAX)?;
|
||||
print_regions(f, "::<", own_counts.lifetimes, usize::MAX)?;
|
||||
|
||||
// FIXME: consider being smart with defaults here too
|
||||
for ty in substs.types().skip(num_types) {
|
||||
for ty in substs.types().skip(own_counts.types) {
|
||||
start_or_continue(f, "::<", ", ")?;
|
||||
ty.print_display(f, self)?;
|
||||
}
|
||||
|
@ -588,18 +601,14 @@ define_print! {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ty::TypeParameterDef {
|
||||
impl fmt::Debug for ty::GenericParamDef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "TypeParameterDef({}, {:?}, {})",
|
||||
self.name,
|
||||
self.def_id,
|
||||
self.index)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ty::RegionParameterDef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "RegionParameterDef({}, {:?}, {})",
|
||||
let type_name = match self.kind {
|
||||
ty::GenericParamDefKind::Lifetime => "Lifetime",
|
||||
ty::GenericParamDefKind::Type(_) => "Type",
|
||||
};
|
||||
write!(f, "{}({}, {:?}, {})",
|
||||
type_name,
|
||||
self.name,
|
||||
self.def_id,
|
||||
self.index)
|
||||
|
|
|
@ -308,7 +308,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> {
|
|||
|
||||
pub fn t_param(&self, index: u32) -> Ty<'tcx> {
|
||||
let name = format!("T{}", index);
|
||||
self.infcx.tcx.mk_param(index, Symbol::intern(&name).as_interned_str())
|
||||
self.infcx.tcx.mk_ty_param(index, Symbol::intern(&name).as_interned_str())
|
||||
}
|
||||
|
||||
pub fn re_early_bound(&self, index: u32, name: &'static str) -> ty::Region<'tcx> {
|
||||
|
|
|
@ -929,10 +929,9 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
|
|||
hir::ImplItemKind::Const(..) => true,
|
||||
hir::ImplItemKind::Method(ref sig, _) => {
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
let types = generics.parent_types as usize + generics.types.len();
|
||||
let needs_inline =
|
||||
(types > 0 || tcx.trans_fn_attrs(def_id).requests_inline())
|
||||
&& !self.metadata_output_only();
|
||||
let needs_inline = (generics.requires_monomorphization(self.tcx) ||
|
||||
tcx.trans_fn_attrs(def_id).requests_inline()) &&
|
||||
!self.metadata_output_only();
|
||||
let is_const_fn = sig.constness == hir::Constness::Const;
|
||||
let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
|
||||
needs_inline || is_const_fn || always_encode_mir
|
||||
|
|
|
@ -197,7 +197,7 @@ use rustc::middle::const_val::ConstVal;
|
|||
use rustc::mir::interpret::{AllocId, ConstValue};
|
||||
use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
|
||||
use rustc::ty::subst::{Substs, Kind};
|
||||
use rustc::ty::{self, TypeFoldable, Ty, TyCtxt};
|
||||
use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind};
|
||||
use rustc::ty::adjustment::CustomCoerceUnsized;
|
||||
use rustc::session::config;
|
||||
use rustc::mir::{self, Location, Promoted};
|
||||
|
@ -1076,7 +1076,7 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> {
|
|||
|
||||
fn item_has_type_parameters<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool {
|
||||
let generics = tcx.generics_of(def_id);
|
||||
generics.parent_types as usize + generics.types.len() > 0
|
||||
generics.requires_monomorphization(tcx)
|
||||
}
|
||||
|
||||
fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
@ -1108,14 +1108,18 @@ fn create_mono_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
continue;
|
||||
}
|
||||
|
||||
if !tcx.generics_of(method.def_id).types.is_empty() {
|
||||
if tcx.generics_of(method.def_id).own_counts().types != 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let substs = Substs::for_item(tcx,
|
||||
method.def_id,
|
||||
|_, _| tcx.types.re_erased,
|
||||
|def, _| trait_ref.substs.type_for_def(def));
|
||||
let substs = Substs::for_item(tcx, method.def_id, |param, _| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => tcx.types.re_erased.into(),
|
||||
GenericParamDefKind::Type(_) => {
|
||||
trait_ref.substs[param.index as usize]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let instance = ty::Instance::resolve(tcx,
|
||||
ty::ParamEnv::reveal_all(),
|
||||
|
|
|
@ -12,7 +12,7 @@ use rustc::hir;
|
|||
use rustc::hir::def_id::DefId;
|
||||
use rustc::infer;
|
||||
use rustc::mir::*;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind};
|
||||
use rustc::ty::subst::{Kind, Subst, Substs};
|
||||
use rustc::ty::maps::Providers;
|
||||
|
||||
|
@ -427,12 +427,12 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
|
|||
) {
|
||||
let tcx = self.tcx;
|
||||
|
||||
let substs = Substs::for_item(
|
||||
tcx,
|
||||
self.def_id,
|
||||
|_, _| tcx.types.re_erased,
|
||||
|_, _| ty
|
||||
);
|
||||
let substs = Substs::for_item(tcx, self.def_id, |param, _| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => tcx.types.re_erased.into(),
|
||||
GenericParamDefKind::Type(_) => ty.into(),
|
||||
}
|
||||
});
|
||||
|
||||
// `func == Clone::clone(&ty) -> ty`
|
||||
let func_ty = tcx.mk_fn_def(self.def_id, substs);
|
||||
|
|
|
@ -357,7 +357,7 @@ fn unsafe_derive_on_repr_packed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: D
|
|||
|
||||
// FIXME: when we make this a hard error, this should have its
|
||||
// own error code.
|
||||
let message = if !tcx.generics_of(def_id).types.is_empty() {
|
||||
let message = if tcx.generics_of(def_id).own_counts().types != 0 {
|
||||
format!("#[derive] can't be used on a #[repr(packed)] struct with \
|
||||
type parameters (error E0133)")
|
||||
} else {
|
||||
|
|
|
@ -184,7 +184,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
|
|||
// evaluate the promoted and replace the constant with the evaluated result
|
||||
Literal::Promoted { index } => {
|
||||
let generics = self.tcx.generics_of(self.source.def_id);
|
||||
if generics.parent_types as usize + generics.types.len() > 0 {
|
||||
if generics.requires_monomorphization(self.tcx) {
|
||||
// FIXME: can't handle code with generics
|
||||
return None;
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
|
|||
self.source.def_id
|
||||
};
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
if generics.parent_types as usize + generics.types.len() > 0 {
|
||||
if generics.requires_monomorphization(self.tcx) {
|
||||
// FIXME: can't handle code with generics
|
||||
return None;
|
||||
}
|
||||
|
@ -317,8 +317,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
|
|||
self.source.def_id
|
||||
};
|
||||
let generics = self.tcx.generics_of(def_id);
|
||||
let has_generics = generics.parent_types as usize + generics.types.len() > 0;
|
||||
if has_generics {
|
||||
if generics.requires_monomorphization(self.tcx) {
|
||||
// FIXME: can't handle code with generics
|
||||
return None;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
|||
use rustc::hir::itemlikevisit::DeepVisitor;
|
||||
use rustc::lint;
|
||||
use rustc::middle::privacy::{AccessLevel, AccessLevels};
|
||||
use rustc::ty::{self, TyCtxt, Ty, TypeFoldable};
|
||||
use rustc::ty::{self, TyCtxt, Ty, TypeFoldable, GenericParamDefKind};
|
||||
use rustc::ty::fold::TypeVisitor;
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc::ty::subst::UnpackedKind;
|
||||
|
@ -399,9 +399,14 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
|
|||
|
||||
impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> {
|
||||
fn generics(&mut self) -> &mut Self {
|
||||
for def in &self.ev.tcx.generics_of(self.item_def_id).types {
|
||||
if def.has_default {
|
||||
self.ev.tcx.type_of(def.def_id).visit_with(self);
|
||||
for param in &self.ev.tcx.generics_of(self.item_def_id).params {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Type(ty) => {
|
||||
if ty.has_default {
|
||||
self.ev.tcx.type_of(param.def_id).visit_with(self);
|
||||
}
|
||||
}
|
||||
GenericParamDefKind::Lifetime => {}
|
||||
}
|
||||
}
|
||||
self
|
||||
|
@ -1335,9 +1340,14 @@ struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
|
|||
|
||||
impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
|
||||
fn generics(&mut self) -> &mut Self {
|
||||
for def in &self.tcx.generics_of(self.item_def_id).types {
|
||||
if def.has_default {
|
||||
self.tcx.type_of(def.def_id).visit_with(self);
|
||||
for param in &self.tcx.generics_of(self.item_def_id).params {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Type(ty) => {
|
||||
if ty.has_default {
|
||||
self.tcx.type_of(param.def_id).visit_with(self);
|
||||
}
|
||||
}
|
||||
GenericParamDefKind::Lifetime => {}
|
||||
}
|
||||
}
|
||||
self
|
||||
|
|
|
@ -14,7 +14,7 @@ use rustc::traits::{FulfillmentContext, Normalized, ObligationCause};
|
|||
use rustc::traits::query::{CanonicalTyGoal, NoSolution};
|
||||
use rustc::traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult};
|
||||
use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt};
|
||||
use rustc::ty::subst::Subst;
|
||||
use rustc::ty::subst::{Subst, Substs};
|
||||
use rustc::util::nodemap::FxHashSet;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use syntax::codemap::{Span, DUMMY_SP};
|
||||
|
@ -278,9 +278,13 @@ crate fn adt_dtorck_constraint<'a, 'tcx>(
|
|||
debug!("dtorck_constraint: {:?}", def);
|
||||
|
||||
if def.is_phantom_data() {
|
||||
// The first generic parameter here is guaranteed to be a type because it's
|
||||
// `PhantomData`.
|
||||
let substs = Substs::identity_for_item(tcx, def_id);
|
||||
assert_eq!(substs.len(), 1);
|
||||
let result = DtorckConstraint {
|
||||
outlives: vec![],
|
||||
dtorck_types: vec![tcx.mk_param_from_def(&tcx.generics_of(def_id).types[0])],
|
||||
dtorck_types: vec![substs.type_at(0)],
|
||||
overflows: vec![],
|
||||
};
|
||||
debug!("dtorck_constraint: {:?} => {:?}", def, result);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
//! the guts are broken up into modules; see the comments in those modules.
|
||||
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(iterator_find_map)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
|
|
@ -117,7 +117,7 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
}) => {
|
||||
let def_id = tcx.hir.local_def_id(node_id);
|
||||
let generics = tcx.generics_of(def_id);
|
||||
if (generics.parent_types == 0 && generics.types.is_empty()) &&
|
||||
if !generics.requires_monomorphization(tcx) &&
|
||||
// Functions marked with #[inline] are only ever translated
|
||||
// with "internal" linkage and are never exported.
|
||||
!Instance::mono(tcx, def_id).def.requires_local(tcx) {
|
||||
|
|
|
@ -25,7 +25,7 @@ use llvm::{ModuleRef, ContextRef, ValueRef};
|
|||
use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray, DIFlags};
|
||||
use rustc::hir::TransFnAttrFlags;
|
||||
use rustc::hir::def_id::{DefId, CrateNum};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::subst::{Substs, UnpackedKind};
|
||||
|
||||
use abi::Abi;
|
||||
use common::CodegenCx;
|
||||
|
@ -390,20 +390,25 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
|||
|
||||
// Again, only create type information if full debuginfo is enabled
|
||||
let template_params: Vec<_> = if cx.sess().opts.debuginfo == FullDebugInfo {
|
||||
let names = get_type_parameter_names(cx, generics);
|
||||
substs.types().zip(names).map(|(ty, name)| {
|
||||
let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
|
||||
let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
|
||||
let name = CString::new(name.as_str().as_bytes()).unwrap();
|
||||
unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
|
||||
DIB(cx),
|
||||
ptr::null_mut(),
|
||||
name.as_ptr(),
|
||||
actual_type_metadata,
|
||||
file_metadata,
|
||||
0,
|
||||
0)
|
||||
let names = get_parameter_names(cx, generics);
|
||||
substs.iter().zip(names).filter_map(|(kind, name)| {
|
||||
if let UnpackedKind::Type(ty) = kind.unpack() {
|
||||
let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
|
||||
let actual_type_metadata =
|
||||
type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
|
||||
let name = CString::new(name.as_str().as_bytes()).unwrap();
|
||||
Some(unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
|
||||
DIB(cx),
|
||||
ptr::null_mut(),
|
||||
name.as_ptr(),
|
||||
actual_type_metadata,
|
||||
file_metadata,
|
||||
0,
|
||||
0)
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).collect()
|
||||
} else {
|
||||
|
@ -413,11 +418,13 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
|||
return create_DIArray(DIB(cx), &template_params[..]);
|
||||
}
|
||||
|
||||
fn get_type_parameter_names(cx: &CodegenCx, generics: &ty::Generics) -> Vec<InternedString> {
|
||||
fn get_parameter_names(cx: &CodegenCx,
|
||||
generics: &ty::Generics)
|
||||
-> Vec<InternedString> {
|
||||
let mut names = generics.parent.map_or(vec![], |def_id| {
|
||||
get_type_parameter_names(cx, cx.tcx.generics_of(def_id))
|
||||
get_parameter_names(cx, cx.tcx.generics_of(def_id))
|
||||
});
|
||||
names.extend(generics.types.iter().map(|param| param.name));
|
||||
names.extend(generics.params.iter().map(|param| param.name));
|
||||
names
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ use namespace::Namespace;
|
|||
use rustc::ty::subst::{Kind, UnpackedKind, Subst, Substs};
|
||||
use rustc::traits;
|
||||
use rustc::ty::{self, RegionKind, Ty, TyCtxt, ToPredicate, TypeFoldable};
|
||||
use rustc::ty::GenericParamDefKind;
|
||||
use rustc::ty::wf::object_region_bounds;
|
||||
use rustc_target::spec::abi;
|
||||
use std::slice;
|
||||
|
@ -43,7 +44,7 @@ pub trait AstConv<'gcx, 'tcx> {
|
|||
-> ty::GenericPredicates<'tcx>;
|
||||
|
||||
/// What lifetime should we use when a lifetime is omitted (and not elided)?
|
||||
fn re_infer(&self, span: Span, _def: Option<&ty::RegionParameterDef>)
|
||||
fn re_infer(&self, span: Span, _def: Option<&ty::GenericParamDef>)
|
||||
-> Option<ty::Region<'tcx>>;
|
||||
|
||||
/// What type should we use when a type is omitted?
|
||||
|
@ -51,7 +52,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,
|
||||
_def: &ty::GenericParamDef,
|
||||
span: Span) -> Ty<'tcx> {
|
||||
self.ty_infer(span)
|
||||
}
|
||||
|
@ -87,6 +88,11 @@ struct ConvertedBinding<'tcx> {
|
|||
span: Span,
|
||||
}
|
||||
|
||||
struct ParamRange {
|
||||
required: usize,
|
||||
accepted: usize
|
||||
}
|
||||
|
||||
/// Dummy type used for the `Self` of a `TraitRef` created for converting
|
||||
/// a trait object, and which gets removed in `ExistentialTraitRef`.
|
||||
/// This type must not appear anywhere in other converted types.
|
||||
|
@ -95,7 +101,7 @@ const TRAIT_OBJECT_DUMMY_SELF: ty::TypeVariants<'static> = ty::TyInfer(ty::Fresh
|
|||
impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
pub fn ast_region_to_region(&self,
|
||||
lifetime: &hir::Lifetime,
|
||||
def: Option<&ty::RegionParameterDef>)
|
||||
def: Option<&ty::GenericParamDef>)
|
||||
-> ty::Region<'tcx>
|
||||
{
|
||||
let tcx = self.tcx();
|
||||
|
@ -208,92 +214,119 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
// region with the current anon region binding (in other words,
|
||||
// whatever & would get replaced with).
|
||||
let decl_generics = tcx.generics_of(def_id);
|
||||
let num_types_provided = parameters.types.len();
|
||||
let expected_num_region_params = decl_generics.regions.len();
|
||||
let supplied_num_region_params = parameters.lifetimes.len();
|
||||
if expected_num_region_params != supplied_num_region_params {
|
||||
report_lifetime_number_error(tcx, span,
|
||||
supplied_num_region_params,
|
||||
expected_num_region_params);
|
||||
let ty_provided = parameters.types.len();
|
||||
let lt_provided = parameters.lifetimes.len();
|
||||
|
||||
let mut lt_accepted = 0;
|
||||
let mut ty_params = ParamRange { required: 0, accepted: 0 };
|
||||
for param in &decl_generics.params {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
lt_accepted += 1;
|
||||
}
|
||||
GenericParamDefKind::Type(ty) => {
|
||||
ty_params.accepted += 1;
|
||||
if !ty.has_default {
|
||||
ty_params.required += 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
if self_ty.is_some() {
|
||||
ty_params.required -= 1;
|
||||
ty_params.accepted -= 1;
|
||||
}
|
||||
|
||||
if lt_accepted != lt_provided {
|
||||
report_lifetime_number_error(tcx, span, lt_provided, lt_accepted);
|
||||
}
|
||||
|
||||
// If a self-type was declared, one should be provided.
|
||||
assert_eq!(decl_generics.has_self, self_ty.is_some());
|
||||
|
||||
// Check the number of type parameters supplied by the user.
|
||||
let ty_param_defs = &decl_generics.types[self_ty.is_some() as usize..];
|
||||
if !infer_types || num_types_provided > ty_param_defs.len() {
|
||||
check_type_argument_count(tcx, span, num_types_provided, ty_param_defs);
|
||||
if !infer_types || ty_provided > ty_params.required {
|
||||
check_type_argument_count(tcx, span, ty_provided, ty_params);
|
||||
}
|
||||
|
||||
let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF);
|
||||
let default_needs_object_self = |p: &ty::TypeParameterDef| {
|
||||
if is_object && p.has_default {
|
||||
if tcx.at(span).type_of(p.def_id).has_self_ty() {
|
||||
// There is no suitable inference default for a type parameter
|
||||
// that references self, in an object type.
|
||||
return true;
|
||||
let default_needs_object_self = |param: &ty::GenericParamDef| {
|
||||
if let GenericParamDefKind::Type(ty) = param.kind {
|
||||
if is_object && ty.has_default {
|
||||
if tcx.at(span).type_of(param.def_id).has_self_ty() {
|
||||
// There is no suitable inference default for a type parameter
|
||||
// that references self, in an object type.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
};
|
||||
|
||||
let substs = Substs::for_item(tcx, def_id, |def, _| {
|
||||
let i = def.index as usize - self_ty.is_some() as usize;
|
||||
if let Some(lifetime) = parameters.lifetimes.get(i) {
|
||||
self.ast_region_to_region(lifetime, Some(def))
|
||||
} else {
|
||||
tcx.types.re_static
|
||||
}
|
||||
}, |def, substs| {
|
||||
let i = def.index as usize;
|
||||
|
||||
// Handle Self first, so we can adjust the index to match the AST.
|
||||
if let (0, Some(ty)) = (i, self_ty) {
|
||||
return ty;
|
||||
}
|
||||
|
||||
let i = i - self_ty.is_some() as usize - decl_generics.regions.len();
|
||||
if i < num_types_provided {
|
||||
// A provided type parameter.
|
||||
self.ast_ty_to_ty(¶meters.types[i])
|
||||
} else if infer_types {
|
||||
// No type parameters were provided, we can infer all.
|
||||
let ty_var = if !default_needs_object_self(def) {
|
||||
self.ty_infer_for_def(def, span)
|
||||
} else {
|
||||
self.ty_infer(span)
|
||||
};
|
||||
ty_var
|
||||
} else if def.has_default {
|
||||
// No type parameter provided, but a default exists.
|
||||
|
||||
// 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 default_needs_object_self(def) {
|
||||
struct_span_err!(tcx.sess, span, E0393,
|
||||
"the type parameter `{}` must be explicitly specified",
|
||||
def.name)
|
||||
.span_label(span, format!("missing reference to `{}`", def.name))
|
||||
.note(&format!("because of the default `Self` reference, \
|
||||
type parameters must be specified on object types"))
|
||||
.emit();
|
||||
tcx.types.err
|
||||
} else {
|
||||
// This is a default type parameter.
|
||||
self.normalize_ty(
|
||||
span,
|
||||
tcx.at(span).type_of(def.def_id)
|
||||
.subst_spanned(tcx, substs, Some(span))
|
||||
)
|
||||
let own_self = self_ty.is_some() as usize;
|
||||
let substs = Substs::for_item(tcx, def_id, |param, substs| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
let i = param.index as usize - own_self;
|
||||
if let Some(lifetime) = parameters.lifetimes.get(i) {
|
||||
self.ast_region_to_region(lifetime, Some(param)).into()
|
||||
} else {
|
||||
tcx.types.re_static.into()
|
||||
}
|
||||
}
|
||||
GenericParamDefKind::Type(ty) => {
|
||||
let i = param.index as usize;
|
||||
|
||||
// Handle Self first, so we can adjust the index to match the AST.
|
||||
if let (0, Some(ty)) = (i, self_ty) {
|
||||
return ty.into();
|
||||
}
|
||||
|
||||
let i = i - (lt_accepted + own_self);
|
||||
if i < ty_provided {
|
||||
// A provided type parameter.
|
||||
self.ast_ty_to_ty(¶meters.types[i]).into()
|
||||
} else if infer_types {
|
||||
// No type parameters were provided, we can infer all.
|
||||
if !default_needs_object_self(param) {
|
||||
self.ty_infer_for_def(param, span).into()
|
||||
} else {
|
||||
self.ty_infer(span).into()
|
||||
}
|
||||
} else if ty.has_default {
|
||||
// No type parameter provided, but a default exists.
|
||||
|
||||
// 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 default_needs_object_self(param) {
|
||||
struct_span_err!(tcx.sess, span, E0393,
|
||||
"the type parameter `{}` must be explicitly \
|
||||
specified",
|
||||
param.name)
|
||||
.span_label(span,
|
||||
format!("missing reference to `{}`", param.name))
|
||||
.note(&format!("because of the default `Self` reference, \
|
||||
type parameters must be specified on object \
|
||||
types"))
|
||||
.emit();
|
||||
tcx.types.err.into()
|
||||
} else {
|
||||
// This is a default type parameter.
|
||||
self.normalize_ty(
|
||||
span,
|
||||
tcx.at(span).type_of(param.def_id)
|
||||
.subst_spanned(tcx, substs, Some(span))
|
||||
).into()
|
||||
}
|
||||
} else {
|
||||
// We've already errored above about the mismatch.
|
||||
tcx.types.err.into()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We've already errored above about the mismatch.
|
||||
tcx.types.err
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -979,8 +1012,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
let item_id = tcx.hir.get_parent_node(node_id);
|
||||
let item_def_id = tcx.hir.local_def_id(item_id);
|
||||
let generics = tcx.generics_of(item_def_id);
|
||||
let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id)];
|
||||
tcx.mk_param(index, tcx.hir.name(node_id).as_interned_str())
|
||||
let index = generics.param_def_id_to_index[&tcx.hir.local_def_id(node_id)];
|
||||
tcx.mk_ty_param(index, tcx.hir.name(node_id).as_interned_str())
|
||||
}
|
||||
Def::SelfTy(_, Some(def_id)) => {
|
||||
// Self in impl (we know the concrete type).
|
||||
|
@ -1124,12 +1157,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
let mut substs = Vec::with_capacity(generics.count());
|
||||
if let Some(parent_id) = generics.parent {
|
||||
let parent_generics = tcx.generics_of(parent_id);
|
||||
Substs::fill_item(
|
||||
&mut substs, tcx, parent_generics,
|
||||
&mut |def, _| tcx.mk_region(
|
||||
ty::ReEarlyBound(def.to_early_bound_region_data())),
|
||||
&mut |def, _| tcx.mk_param_from_def(def)
|
||||
);
|
||||
Substs::fill_item(&mut substs, tcx, parent_generics, &mut |param, _| {
|
||||
tcx.mk_param_from_def(param)
|
||||
});
|
||||
|
||||
// Replace all lifetimes with 'static
|
||||
for subst in &mut substs {
|
||||
|
@ -1139,10 +1169,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
|||
}
|
||||
debug!("impl_trait_ty_to_ty: substs from parent = {:?}", substs);
|
||||
}
|
||||
assert_eq!(substs.len(), generics.parent_count());
|
||||
assert_eq!(substs.len(), generics.parent_count);
|
||||
|
||||
// Fill in our own generics with the resolved lifetimes
|
||||
assert_eq!(lifetimes.len(), generics.own_count());
|
||||
assert_eq!(lifetimes.len(), generics.params.len());
|
||||
substs.extend(lifetimes.iter().map(|lt| Kind::from(self.ast_region_to_region(lt, None))));
|
||||
|
||||
debug!("impl_trait_ty_to_ty: final substs = {:?}", substs);
|
||||
|
@ -1299,10 +1329,12 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
|||
(auto_traits, trait_bounds)
|
||||
}
|
||||
|
||||
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.has_default).count();
|
||||
fn check_type_argument_count(tcx: TyCtxt,
|
||||
span: Span,
|
||||
supplied: usize,
|
||||
ty_params: ParamRange)
|
||||
{
|
||||
let (required, accepted) = (ty_params.required, ty_params.accepted);
|
||||
if supplied < required {
|
||||
let expected = if required < accepted {
|
||||
"expected at least"
|
||||
|
|
|
@ -18,7 +18,7 @@ use rustc::infer::{InferOk, InferResult};
|
|||
use rustc::infer::LateBoundRegionConversionTime;
|
||||
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||
use rustc::traits::error_reporting::ArgKind;
|
||||
use rustc::ty::{self, ToPolyTraitRef, Ty};
|
||||
use rustc::ty::{self, ToPolyTraitRef, Ty, GenericParamDefKind};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::TypeFoldable;
|
||||
use std::cmp;
|
||||
|
@ -104,15 +104,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// inference phase (`upvar.rs`).
|
||||
let base_substs =
|
||||
Substs::identity_for_item(self.tcx, self.tcx.closure_base_def_id(expr_def_id));
|
||||
let substs = base_substs.extend_to(
|
||||
self.tcx,
|
||||
expr_def_id,
|
||||
|_, _| span_bug!(expr.span, "closure has region param"),
|
||||
|_, _| {
|
||||
self.infcx
|
||||
.next_ty_var(TypeVariableOrigin::ClosureSynthetic(expr.span))
|
||||
},
|
||||
);
|
||||
let substs = base_substs.extend_to(self.tcx,expr_def_id, |param, _| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
span_bug!(expr.span, "closure has region param")
|
||||
}
|
||||
GenericParamDefKind::Type(_) => {
|
||||
self.infcx
|
||||
.next_ty_var(TypeVariableOrigin::ClosureSynthetic(expr.span)).into()
|
||||
}
|
||||
}
|
||||
});
|
||||
if let Some(GeneratorTypes { yield_ty, interior, movability }) = generator_types {
|
||||
let substs = ty::GeneratorSubsts { substs };
|
||||
self.demand_eqtype(
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
use rustc::hir::{self, ImplItemKind, TraitItemKind};
|
||||
use rustc::infer::{self, InferOk};
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::ty::{self, TyCtxt, GenericParamDefKind};
|
||||
use rustc::ty::util::ExplicitSelf;
|
||||
use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
|
||||
use rustc::ty::error::{ExpectedFound, TypeError};
|
||||
|
@ -357,8 +357,8 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
trait_to_skol_substs: &Substs<'tcx>)
|
||||
-> Result<(), ErrorReported> {
|
||||
let span = tcx.sess.codemap().def_span(span);
|
||||
let trait_params = &trait_generics.regions[..];
|
||||
let impl_params = &impl_generics.regions[..];
|
||||
let trait_params = trait_generics.own_counts().lifetimes;
|
||||
let impl_params = impl_generics.own_counts().lifetimes;
|
||||
|
||||
debug!("check_region_bounds_on_impl_method: \
|
||||
trait_generics={:?} \
|
||||
|
@ -377,7 +377,7 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
// but found 0" it's confusing, because it looks like there
|
||||
// are zero. Since I don't quite know how to phrase things at
|
||||
// the moment, give a kind of vague error message.
|
||||
if trait_params.len() != impl_params.len() {
|
||||
if trait_params != impl_params {
|
||||
let mut err = struct_span_err!(tcx.sess,
|
||||
span,
|
||||
E0195,
|
||||
|
@ -574,8 +574,8 @@ fn compare_number_of_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
-> Result<(), ErrorReported> {
|
||||
let impl_m_generics = tcx.generics_of(impl_m.def_id);
|
||||
let trait_m_generics = tcx.generics_of(trait_m.def_id);
|
||||
let num_impl_m_type_params = impl_m_generics.types.len();
|
||||
let num_trait_m_type_params = trait_m_generics.types.len();
|
||||
let num_impl_m_type_params = impl_m_generics.own_counts().types;
|
||||
let num_trait_m_type_params = trait_m_generics.own_counts().types;
|
||||
if num_impl_m_type_params != num_trait_m_type_params {
|
||||
let impl_m_node_id = tcx.hir.as_local_node_id(impl_m.def_id).unwrap();
|
||||
let impl_m_item = tcx.hir.expect_impl_item(impl_m_node_id);
|
||||
|
@ -728,11 +728,24 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
let mut error_found = false;
|
||||
let impl_m_generics = tcx.generics_of(impl_m.def_id);
|
||||
let trait_m_generics = tcx.generics_of(trait_m.def_id);
|
||||
for (impl_ty, trait_ty) in impl_m_generics.types.iter().zip(trait_m_generics.types.iter()) {
|
||||
if impl_ty.synthetic != trait_ty.synthetic {
|
||||
let impl_node_id = tcx.hir.as_local_node_id(impl_ty.def_id).unwrap();
|
||||
let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Type(ty) => Some((param.def_id, ty.synthetic)),
|
||||
GenericParamDefKind::Lifetime => None,
|
||||
}
|
||||
});
|
||||
let trait_m_type_params = trait_m_generics.params.iter().filter_map(|param| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Type(ty) => Some((param.def_id, ty.synthetic)),
|
||||
GenericParamDefKind::Lifetime => None,
|
||||
}
|
||||
});
|
||||
for ((impl_def_id, impl_synthetic),
|
||||
(trait_def_id, trait_synthetic)) in impl_m_type_params.zip(trait_m_type_params) {
|
||||
if impl_synthetic != trait_synthetic {
|
||||
let impl_node_id = tcx.hir.as_local_node_id(impl_def_id).unwrap();
|
||||
let impl_span = tcx.hir.span(impl_node_id);
|
||||
let trait_span = tcx.def_span(trait_ty.def_id);
|
||||
let trait_span = tcx.def_span(trait_def_id);
|
||||
let mut err = struct_span_err!(tcx.sess,
|
||||
impl_span,
|
||||
E0643,
|
||||
|
|
|
@ -45,7 +45,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
}
|
||||
}
|
||||
|
||||
let i_n_tps = tcx.generics_of(def_id).types.len();
|
||||
let i_n_tps = tcx.generics_of(def_id).own_counts().types;
|
||||
if i_n_tps != n_tps {
|
||||
let span = match it.node {
|
||||
hir::ForeignItemFn(_, _, ref generics) => generics.span,
|
||||
|
@ -76,7 +76,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
/// and in libcore/intrinsics.rs
|
||||
pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
it: &hir::ForeignItem) {
|
||||
let param = |n| tcx.mk_param(n, Symbol::intern(&format!("P{}", n)).as_interned_str());
|
||||
let param = |n| tcx.mk_ty_param(n, Symbol::intern(&format!("P{}", n)).as_interned_str());
|
||||
let name = it.name.as_str();
|
||||
let (n_tps, inputs, output) = if name.starts_with("atomic_") {
|
||||
let split : Vec<&str> = name.split('_').collect();
|
||||
|
@ -342,11 +342,11 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
it: &hir::ForeignItem) {
|
||||
let param = |n| {
|
||||
let name = Symbol::intern(&format!("P{}", n)).as_interned_str();
|
||||
tcx.mk_param(n, name)
|
||||
tcx.mk_ty_param(n, name)
|
||||
};
|
||||
|
||||
let def_id = tcx.hir.local_def_id(it.id);
|
||||
let i_n_tps = tcx.generics_of(def_id).types.len();
|
||||
let i_n_tps = tcx.generics_of(def_id).own_counts().types;
|
||||
let name = it.name.as_str();
|
||||
|
||||
let (n_tps, inputs, output) = match &*name {
|
||||
|
|
|
@ -15,7 +15,7 @@ use check::{FnCtxt, PlaceOp, callee, Needs};
|
|||
use hir::def_id::DefId;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::traits;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::ty::{self, Ty, GenericParamDefKind};
|
||||
use rustc::ty::subst::Subst;
|
||||
use rustc::ty::adjustment::{Adjustment, Adjust, OverloadedDeref};
|
||||
use rustc::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
|
||||
|
@ -314,30 +314,32 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
|||
|
||||
// Create subst for early-bound lifetime parameters, combining
|
||||
// parameters from the type and those from the method.
|
||||
assert_eq!(method_generics.parent_count(), parent_substs.len());
|
||||
assert_eq!(method_generics.parent_count, parent_substs.len());
|
||||
let provided = &segment.parameters;
|
||||
Substs::for_item(self.tcx, pick.item.def_id, |def, _| {
|
||||
let i = def.index as usize;
|
||||
let own_counts = method_generics.own_counts();
|
||||
Substs::for_item(self.tcx, pick.item.def_id, |param, _| {
|
||||
let i = param.index as usize;
|
||||
if i < parent_substs.len() {
|
||||
parent_substs.region_at(i)
|
||||
} else if let Some(lifetime)
|
||||
= provided.as_ref().and_then(|p| p.lifetimes.get(i - parent_substs.len())) {
|
||||
AstConv::ast_region_to_region(self.fcx, lifetime, Some(def))
|
||||
parent_substs[i]
|
||||
} else {
|
||||
self.region_var_for_def(self.span, def)
|
||||
}
|
||||
}, |def, _cur_substs| {
|
||||
let i = def.index as usize;
|
||||
if i < parent_substs.len() {
|
||||
parent_substs.type_at(i)
|
||||
} else if let Some(ast_ty)
|
||||
= provided.as_ref().and_then(|p| {
|
||||
p.types.get(i - parent_substs.len() - method_generics.regions.len())
|
||||
})
|
||||
{
|
||||
self.to_ty(ast_ty)
|
||||
} else {
|
||||
self.type_var_for_def(self.span, def)
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
if let Some(lifetime) = provided.as_ref().and_then(|p| {
|
||||
p.lifetimes.get(i - parent_substs.len())
|
||||
}) {
|
||||
return AstConv::ast_region_to_region(
|
||||
self.fcx, lifetime, Some(param)).into();
|
||||
}
|
||||
}
|
||||
GenericParamDefKind::Type(_) => {
|
||||
if let Some(ast_ty) = provided.as_ref().and_then(|p| {
|
||||
p.types.get(i - parent_substs.len() - own_counts.lifetimes)
|
||||
}) {
|
||||
return self.to_ty(ast_ty).into();
|
||||
}
|
||||
}
|
||||
}
|
||||
self.var_for_def(self.span, param)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ use namespace::Namespace;
|
|||
use rustc::ty::subst::Substs;
|
||||
use rustc::traits;
|
||||
use rustc::ty::{self, Ty, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable};
|
||||
use rustc::ty::GenericParamDefKind;
|
||||
use rustc::ty::subst::Subst;
|
||||
use rustc::infer::{self, InferOk};
|
||||
|
||||
|
@ -253,17 +254,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
trait_def_id);
|
||||
|
||||
// Construct a trait-reference `self_ty : Trait<input_tys>`
|
||||
let substs = Substs::for_item(self.tcx,
|
||||
trait_def_id,
|
||||
|def, _| self.region_var_for_def(span, def),
|
||||
|def, _substs| {
|
||||
if def.index == 0 {
|
||||
self_ty
|
||||
} else if let Some(ref input_types) = opt_input_types {
|
||||
input_types[def.index as usize - 1]
|
||||
} else {
|
||||
self.type_var_for_def(span, def)
|
||||
let substs = Substs::for_item(self.tcx, trait_def_id, |param, _| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {}
|
||||
GenericParamDefKind::Type(_) => {
|
||||
if param.index == 0 {
|
||||
return self_ty.into();
|
||||
} else if let Some(ref input_types) = opt_input_types {
|
||||
return input_types[param.index as usize - 1].into();
|
||||
}
|
||||
}
|
||||
}
|
||||
self.var_for_def(span, param)
|
||||
});
|
||||
|
||||
let trait_ref = ty::TraitRef::new(trait_def_id, substs);
|
||||
|
@ -288,8 +290,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
let method_item = self.associated_item(trait_def_id, m_name, Namespace::Value).unwrap();
|
||||
let def_id = method_item.def_id;
|
||||
let generics = tcx.generics_of(def_id);
|
||||
assert_eq!(generics.types.len(), 0);
|
||||
assert_eq!(generics.regions.len(), 0);
|
||||
assert_eq!(generics.params.len(), 0);
|
||||
|
||||
debug!("lookup_in_trait_adjusted: method_item={:?}", method_item);
|
||||
let mut obligations = vec![];
|
||||
|
|
|
@ -20,6 +20,7 @@ use namespace::Namespace;
|
|||
use rustc::ty::subst::{Subst, Substs};
|
||||
use rustc::traits::{self, ObligationCause};
|
||||
use rustc::ty::{self, Ty, ToPolyTraitRef, ToPredicate, TraitRef, TypeFoldable};
|
||||
use rustc::ty::GenericParamDefKind;
|
||||
use rustc::infer::type_variable::TypeVariableOrigin;
|
||||
use rustc::util::nodemap::FxHashSet;
|
||||
use rustc::infer::{self, InferOk};
|
||||
|
@ -1378,31 +1379,28 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||
// method yet. So create fresh variables here for those too,
|
||||
// if there are any.
|
||||
let generics = self.tcx.generics_of(method);
|
||||
assert_eq!(substs.types().count(), generics.parent_types as usize);
|
||||
assert_eq!(substs.regions().count(), generics.parent_regions as usize);
|
||||
assert_eq!(substs.len(), generics.parent_count as usize);
|
||||
|
||||
// Erase any late-bound regions from the method and substitute
|
||||
// in the values from the substitution.
|
||||
let xform_fn_sig = self.erase_late_bound_regions(&fn_sig);
|
||||
|
||||
if generics.types.is_empty() && generics.regions.is_empty() {
|
||||
if generics.params.is_empty() {
|
||||
xform_fn_sig.subst(self.tcx, substs)
|
||||
} else {
|
||||
let substs = Substs::for_item(self.tcx, method, |def, _| {
|
||||
let i = def.index as usize;
|
||||
let substs = Substs::for_item(self.tcx, method, |param, _| {
|
||||
let i = param.index as usize;
|
||||
if i < substs.len() {
|
||||
substs.region_at(i)
|
||||
substs[i]
|
||||
} else {
|
||||
// In general, during probe we erase regions. See
|
||||
// `impl_self_ty()` for an explanation.
|
||||
self.tcx.types.re_erased
|
||||
}
|
||||
}, |def, _cur_substs| {
|
||||
let i = def.index as usize;
|
||||
if i < substs.len() {
|
||||
substs.type_at(i)
|
||||
} else {
|
||||
self.type_var_for_def(self.span, def)
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
// In general, during probe we erase regions. See
|
||||
// `impl_self_ty()` for an explanation.
|
||||
self.tcx.types.re_erased.into()
|
||||
}
|
||||
GenericParamDefKind::Type(_) => self.var_for_def(self.span, param),
|
||||
}
|
||||
}
|
||||
});
|
||||
xform_fn_sig.subst(self.tcx, substs)
|
||||
|
@ -1415,12 +1413,15 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn fresh_item_substs(&self, def_id: DefId) -> &'tcx Substs<'tcx> {
|
||||
Substs::for_item(self.tcx,
|
||||
def_id,
|
||||
|_, _| self.tcx.types.re_erased,
|
||||
|_, _| self.next_ty_var(
|
||||
TypeVariableOrigin::SubstitutionPlaceholder(
|
||||
self.tcx.def_span(def_id))))
|
||||
Substs::for_item(self.tcx, def_id, |param, _| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => self.tcx.types.re_erased.into(),
|
||||
GenericParamDefKind::Type(_) => {
|
||||
self.next_ty_var(TypeVariableOrigin::SubstitutionPlaceholder(
|
||||
self.tcx.def_span(def_id))).into()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Replace late-bound-regions bound by `value` with `'static` using
|
||||
|
|
|
@ -94,9 +94,9 @@ use rustc::infer::anon_types::AnonTypeDecl;
|
|||
use rustc::infer::type_variable::{TypeVariableOrigin};
|
||||
use rustc::middle::region;
|
||||
use rustc::mir::interpret::{GlobalId};
|
||||
use rustc::ty::subst::{Kind, Subst, Substs};
|
||||
use rustc::ty::subst::{Kind, UnpackedKind, Subst, Substs};
|
||||
use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine};
|
||||
use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPredicate};
|
||||
use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind, Visibility, ToPredicate};
|
||||
use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
|
||||
use rustc::ty::fold::TypeFoldable;
|
||||
use rustc::ty::maps::Providers;
|
||||
|
@ -1239,7 +1239,7 @@ pub fn check_item_type<'a,'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Item
|
|||
} else {
|
||||
for item in &m.items {
|
||||
let generics = tcx.generics_of(tcx.hir.local_def_id(item.id));
|
||||
if !generics.types.is_empty() {
|
||||
if generics.params.len() - generics.own_counts().lifetimes != 0 {
|
||||
let mut err = struct_span_err!(tcx.sess, item.span, E0044,
|
||||
"foreign items may not have type parameters");
|
||||
err.span_label(item.span, "can't have type parameters");
|
||||
|
@ -1716,7 +1716,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
|
|||
let item_id = tcx.hir.ty_param_owner(node_id);
|
||||
let item_def_id = tcx.hir.local_def_id(item_id);
|
||||
let generics = tcx.generics_of(item_def_id);
|
||||
let index = generics.type_param_to_index[&def_id];
|
||||
let index = generics.param_def_id_to_index[&def_id];
|
||||
ty::GenericPredicates {
|
||||
parent: None,
|
||||
predicates: self.param_env.caller_bounds.iter().filter(|predicate| {
|
||||
|
@ -1730,7 +1730,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn re_infer(&self, span: Span, def: Option<&ty::RegionParameterDef>)
|
||||
fn re_infer(&self, span: Span, def: Option<&ty::GenericParamDef>)
|
||||
-> Option<ty::Region<'tcx>> {
|
||||
let v = match def {
|
||||
Some(def) => infer::EarlyBoundRegion(span, def.name),
|
||||
|
@ -1744,9 +1744,12 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
fn ty_infer_for_def(&self,
|
||||
ty_param_def: &ty::TypeParameterDef,
|
||||
ty_param_def: &ty::GenericParamDef,
|
||||
span: Span) -> Ty<'tcx> {
|
||||
self.type_var_for_def(span, ty_param_def)
|
||||
if let UnpackedKind::Type(ty) = self.var_for_def(span, ty_param_def).unpack() {
|
||||
return ty;
|
||||
}
|
||||
unreachable!()
|
||||
}
|
||||
|
||||
fn projected_ty_from_poly_trait_ref(&self,
|
||||
|
@ -4751,41 +4754,24 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
|
||||
let (fn_start, has_self) = match (type_segment, fn_segment) {
|
||||
(_, Some((_, generics))) => {
|
||||
(generics.parent_count(), generics.has_self)
|
||||
(generics.parent_count, generics.has_self)
|
||||
}
|
||||
(Some((_, generics)), None) => {
|
||||
(generics.own_count(), generics.has_self)
|
||||
(generics.params.len(), generics.has_self)
|
||||
}
|
||||
(None, None) => (0, false)
|
||||
};
|
||||
let substs = Substs::for_item(self.tcx, def.def_id(), |def, _| {
|
||||
let mut i = def.index as usize;
|
||||
let substs = Substs::for_item(self.tcx, def.def_id(), |param, substs| {
|
||||
let mut i = param.index as usize;
|
||||
|
||||
let segment = if i < fn_start {
|
||||
i -= has_self as usize;
|
||||
type_segment
|
||||
} else {
|
||||
i -= fn_start;
|
||||
fn_segment
|
||||
};
|
||||
let lifetimes = segment.map_or(&[][..], |(s, _)| {
|
||||
s.parameters.as_ref().map_or(&[][..], |p| &p.lifetimes[..])
|
||||
});
|
||||
|
||||
if let Some(lifetime) = lifetimes.get(i) {
|
||||
AstConv::ast_region_to_region(self, lifetime, Some(def))
|
||||
} else {
|
||||
self.re_infer(span, Some(def)).unwrap()
|
||||
}
|
||||
}, |def, substs| {
|
||||
let mut i = def.index as usize;
|
||||
|
||||
let segment = if i < fn_start {
|
||||
// Handle Self first, so we can adjust the index to match the AST.
|
||||
if has_self && i == 0 {
|
||||
return opt_self_ty.unwrap_or_else(|| {
|
||||
self.type_var_for_def(span, def)
|
||||
});
|
||||
if let GenericParamDefKind::Type(_) = param.kind {
|
||||
// Handle Self first, so we can adjust the index to match the AST.
|
||||
if has_self && i == 0 {
|
||||
return opt_self_ty.map(|ty| Kind::from(ty)).unwrap_or_else(|| {
|
||||
self.var_for_def(span, param)
|
||||
});
|
||||
}
|
||||
}
|
||||
i -= has_self as usize;
|
||||
type_segment
|
||||
|
@ -4793,31 +4779,52 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
i -= fn_start;
|
||||
fn_segment
|
||||
};
|
||||
let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| {
|
||||
(s.parameters.as_ref().map_or(&[][..], |p| &p.types[..]), s.infer_types)
|
||||
});
|
||||
|
||||
// Skip over the lifetimes in the same segment.
|
||||
if let Some((_, generics)) = segment {
|
||||
i -= generics.regions.len();
|
||||
}
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
let lifetimes = segment.map_or(&[][..], |(s, _)| {
|
||||
s.parameters.as_ref().map_or(&[][..], |p| &p.lifetimes[..])
|
||||
});
|
||||
|
||||
if let Some(ast_ty) = types.get(i) {
|
||||
// A provided type parameter.
|
||||
self.to_ty(ast_ty)
|
||||
} else if !infer_types && def.has_default {
|
||||
// No type parameter provided, but a default exists.
|
||||
let default = self.tcx.type_of(def.def_id);
|
||||
self.normalize_ty(
|
||||
span,
|
||||
default.subst_spanned(self.tcx, substs, Some(span))
|
||||
)
|
||||
} else {
|
||||
// No type parameters were provided, we can infer all.
|
||||
// This can also be reached in some error cases:
|
||||
// We prefer to use inference variables instead of
|
||||
// TyError to let type inference recover somewhat.
|
||||
self.type_var_for_def(span, def)
|
||||
if let Some(lifetime) = lifetimes.get(i) {
|
||||
AstConv::ast_region_to_region(self, lifetime, Some(param)).into()
|
||||
} else {
|
||||
self.re_infer(span, Some(param)).unwrap().into()
|
||||
}
|
||||
}
|
||||
GenericParamDefKind::Type(_) => {
|
||||
let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| {
|
||||
(s.parameters.as_ref().map_or(&[][..], |p| &p.types[..]), s.infer_types)
|
||||
});
|
||||
|
||||
// Skip over the lifetimes in the same segment.
|
||||
if let Some((_, generics)) = segment {
|
||||
i -= generics.own_counts().lifetimes;
|
||||
}
|
||||
|
||||
let has_default = match param.kind {
|
||||
GenericParamDefKind::Type(ty) => ty.has_default,
|
||||
_ => unreachable!()
|
||||
};
|
||||
|
||||
if let Some(ast_ty) = types.get(i) {
|
||||
// A provided type parameter.
|
||||
self.to_ty(ast_ty).into()
|
||||
} else if !infer_types && has_default {
|
||||
// No type parameter provided, but a default exists.
|
||||
let default = self.tcx.type_of(param.def_id);
|
||||
self.normalize_ty(
|
||||
span,
|
||||
default.subst_spanned(self.tcx, substs, Some(span))
|
||||
).into()
|
||||
} else {
|
||||
// No type parameters were provided, we can infer all.
|
||||
// This can also be reached in some error cases:
|
||||
// We prefer to use inference variables instead of
|
||||
// TyError to let type inference recover somewhat.
|
||||
self.var_for_def(span, param)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -4917,18 +4924,40 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
format!("{} type parameter{}", n, if n == 1 { "" } else { "s" })
|
||||
};
|
||||
|
||||
// Check provided type parameters.
|
||||
let type_defs = segment.map_or(&[][..], |(_, generics)| {
|
||||
if generics.parent.is_none() {
|
||||
&generics.types[generics.has_self as usize..]
|
||||
} else {
|
||||
&generics.types
|
||||
}
|
||||
});
|
||||
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());
|
||||
// Check provided parameters.
|
||||
let ((ty_required, ty_accepted), lt_accepted) =
|
||||
segment.map_or(((0, 0), 0), |(_, generics)| {
|
||||
struct ParamRange {
|
||||
required: usize,
|
||||
accepted: usize
|
||||
};
|
||||
|
||||
let mut lt_accepted = 0;
|
||||
let mut ty_params = ParamRange { required: 0, accepted: 0 };
|
||||
for param in &generics.params {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
lt_accepted += 1;
|
||||
}
|
||||
GenericParamDefKind::Type(ty) => {
|
||||
ty_params.accepted += 1;
|
||||
if !ty.has_default {
|
||||
ty_params.required += 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
if generics.parent.is_none() && generics.has_self {
|
||||
ty_params.required -= 1;
|
||||
ty_params.accepted -= 1;
|
||||
}
|
||||
|
||||
((ty_params.required, ty_params.accepted), lt_accepted)
|
||||
});
|
||||
|
||||
if types.len() > ty_accepted {
|
||||
let span = types[ty_accepted].span;
|
||||
let expected_text = count_type_params(ty_accepted);
|
||||
let actual_text = count_type_params(types.len());
|
||||
struct_span_err!(self.tcx.sess, span, E0087,
|
||||
"too many type parameters provided: \
|
||||
|
@ -4941,8 +4970,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
// type parameters, we force instantiate_value_path to
|
||||
// use inference variables instead of the provided types.
|
||||
*segment = None;
|
||||
} else if types.len() < required_len && !infer_types && !supress_mismatch_error {
|
||||
let expected_text = count_type_params(required_len);
|
||||
} else if types.len() < ty_required && !infer_types && !supress_mismatch_error {
|
||||
let expected_text = count_type_params(ty_required);
|
||||
let actual_text = count_type_params(types.len());
|
||||
struct_span_err!(self.tcx.sess, span, E0089,
|
||||
"too few type parameters provided: \
|
||||
|
@ -4956,10 +4985,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
AstConv::prohibit_projection(self, bindings[0].span);
|
||||
}
|
||||
|
||||
// Check provided lifetime parameters.
|
||||
let lifetime_defs = segment.map_or(&[][..], |(_, generics)| &generics.regions);
|
||||
let required_len = lifetime_defs.len();
|
||||
|
||||
// Prohibit explicit lifetime arguments if late bound lifetime parameters are present.
|
||||
let has_late_bound_lifetime_defs =
|
||||
segment.map_or(None, |(_, generics)| generics.has_late_bound_regions);
|
||||
|
@ -4968,8 +4993,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
let primary_msg = "cannot specify lifetime arguments explicitly \
|
||||
if late bound lifetime parameters are present";
|
||||
let note_msg = "the late bound lifetime parameter is introduced here";
|
||||
if !is_method_call && (lifetimes.len() > lifetime_defs.len() ||
|
||||
lifetimes.len() < required_len && !infer_lifetimes) {
|
||||
if !is_method_call && (lifetimes.len() > lt_accepted ||
|
||||
lifetimes.len() < lt_accepted && !infer_lifetimes) {
|
||||
let mut err = self.tcx.sess.struct_span_err(lifetimes[0].span, primary_msg);
|
||||
err.span_note(span_late, note_msg);
|
||||
err.emit();
|
||||
|
@ -4983,9 +5008,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
if lifetimes.len() > lifetime_defs.len() {
|
||||
let span = lifetimes[lifetime_defs.len()].span;
|
||||
let expected_text = count_lifetime_params(lifetime_defs.len());
|
||||
if lifetimes.len() > lt_accepted {
|
||||
let span = lifetimes[lt_accepted].span;
|
||||
let expected_text = count_lifetime_params(lt_accepted);
|
||||
let actual_text = count_lifetime_params(lifetimes.len());
|
||||
struct_span_err!(self.tcx.sess, span, E0088,
|
||||
"too many lifetime parameters provided: \
|
||||
|
@ -4993,8 +5018,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
expected_text, actual_text)
|
||||
.span_label(span, format!("expected {}", expected_text))
|
||||
.emit();
|
||||
} else if lifetimes.len() < required_len && !infer_lifetimes {
|
||||
let expected_text = count_lifetime_params(lifetime_defs.len());
|
||||
} else if lifetimes.len() < lt_accepted && !infer_lifetimes {
|
||||
let expected_text = count_lifetime_params(lt_accepted);
|
||||
let actual_text = count_lifetime_params(lifetimes.len());
|
||||
struct_span_err!(self.tcx.sess, span, E0090,
|
||||
"too few lifetime parameters provided: \
|
||||
|
@ -5010,17 +5035,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
span: Span,
|
||||
segment: &mut Option<(&hir::PathSegment, &ty::Generics)>)
|
||||
-> bool {
|
||||
use hir::SyntheticTyParamKind::*;
|
||||
|
||||
let segment = segment.map(|(path_segment, generics)| {
|
||||
let explicit = !path_segment.infer_types;
|
||||
let impl_trait = generics.types.iter()
|
||||
.any(|ty_param| {
|
||||
match ty_param.synthetic {
|
||||
Some(ImplTrait) => true,
|
||||
_ => false,
|
||||
}
|
||||
});
|
||||
let impl_trait = generics.params.iter().any(|param| {
|
||||
if let ty::GenericParamDefKind::Type(ty) = param.kind {
|
||||
if let Some(hir::SyntheticTyParamKind::ImplTrait) = ty.synthetic {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
});
|
||||
|
||||
if explicit && impl_trait {
|
||||
let mut err = struct_span_err! {
|
||||
|
|
|
@ -13,7 +13,8 @@ use constrained_type_params::{identify_constrained_type_params, Parameter};
|
|||
|
||||
use hir::def_id::DefId;
|
||||
use rustc::traits::{self, ObligationCauseCode};
|
||||
use rustc::ty::{self, Lift, Ty, TyCtxt};
|
||||
use rustc::ty::{self, Lift, Ty, TyCtxt, GenericParamDefKind};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::util::ExplicitSelf;
|
||||
use rustc::util::nodemap::{FxHashSet, FxHashMap};
|
||||
use rustc::middle::lang_items;
|
||||
|
@ -187,7 +188,7 @@ fn check_associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
fcx.register_wf_obligation(ty, span, code.clone());
|
||||
}
|
||||
ty::AssociatedKind::Method => {
|
||||
reject_shadowing_type_parameters(fcx.tcx, item.def_id);
|
||||
reject_shadowing_parameters(fcx.tcx, item.def_id);
|
||||
let sig = fcx.tcx.fn_sig(item.def_id);
|
||||
let sig = fcx.normalize_associated_types_in(span, &sig);
|
||||
check_fn_or_method(tcx, fcx, span, sig,
|
||||
|
@ -368,21 +369,31 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
|
|||
let mut substituted_predicates = Vec::new();
|
||||
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let is_our_default = |def: &ty::TypeParameterDef|
|
||||
def.has_default && def.index >= generics.parent_count() as u32;
|
||||
let is_our_default = |def: &ty::GenericParamDef| {
|
||||
match def.kind {
|
||||
GenericParamDefKind::Type(ty) => {
|
||||
ty.has_default && def.index >= generics.parent_count as u32
|
||||
}
|
||||
_ => unreachable!()
|
||||
}
|
||||
};
|
||||
|
||||
// Check that concrete defaults are well-formed. See test `type-check-defaults.rs`.
|
||||
// For example this forbids the declaration:
|
||||
// struct Foo<T = Vec<[u32]>> { .. }
|
||||
// Here the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
|
||||
for d in generics.types.iter().cloned().filter(is_our_default).map(|p| p.def_id) {
|
||||
let ty = fcx.tcx.type_of(d);
|
||||
// ignore dependent defaults -- that is, where the default of one type
|
||||
// parameter includes another (e.g., <T, U = T>). In those cases, we can't
|
||||
// be sure if it will error or not as user might always specify the other.
|
||||
if !ty.needs_subst() {
|
||||
fcx.register_wf_obligation(ty, fcx.tcx.def_span(d),
|
||||
ObligationCauseCode::MiscObligation);
|
||||
for param in &generics.params {
|
||||
if let GenericParamDefKind::Type(_) = param.kind {
|
||||
if is_our_default(¶m) {
|
||||
let ty = fcx.tcx.type_of(param.def_id);
|
||||
// ignore dependent defaults -- that is, where the default of one type
|
||||
// parameter includes another (e.g., <T, U = T>). In those cases, we can't
|
||||
// be sure if it will error or not as user might always specify the other.
|
||||
if !ty.needs_subst() {
|
||||
fcx.register_wf_obligation(ty, fcx.tcx.def_span(param.def_id),
|
||||
ObligationCauseCode::MiscObligation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -394,22 +405,27 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>,
|
|||
// For more examples see tests `defaults-well-formedness.rs` and `type-check-defaults.rs`.
|
||||
//
|
||||
// First we build the defaulted substitution.
|
||||
let substs = ty::subst::Substs::for_item(fcx.tcx, def_id, |def, _| {
|
||||
// All regions are identity.
|
||||
fcx.tcx.mk_region(ty::ReEarlyBound(def.to_early_bound_region_data()))
|
||||
}, |def, _| {
|
||||
// If the param has a default,
|
||||
if is_our_default(def) {
|
||||
let default_ty = fcx.tcx.type_of(def.def_id);
|
||||
// and it's not a dependent default
|
||||
if !default_ty.needs_subst() {
|
||||
// then substitute with the default.
|
||||
return default_ty;
|
||||
}
|
||||
let substs = Substs::for_item(fcx.tcx, def_id, |param, _| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => {
|
||||
// All regions are identity.
|
||||
fcx.tcx.mk_param_from_def(param)
|
||||
}
|
||||
// Mark unwanted params as err.
|
||||
fcx.tcx.types.err
|
||||
});
|
||||
GenericParamDefKind::Type(_) => {
|
||||
// If the param has a default,
|
||||
if is_our_default(param) {
|
||||
let default_ty = fcx.tcx.type_of(param.def_id);
|
||||
// and it's not a dependent default
|
||||
if !default_ty.needs_subst() {
|
||||
// then substitute with the default.
|
||||
return default_ty.into();
|
||||
}
|
||||
}
|
||||
// Mark unwanted params as err.
|
||||
fcx.tcx.types.err.into()
|
||||
}
|
||||
}
|
||||
});
|
||||
// Now we build the substituted predicates.
|
||||
for &pred in predicates.predicates.iter() {
|
||||
struct CountParams { params: FxHashSet<u32> }
|
||||
|
@ -638,15 +654,25 @@ fn report_bivariance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
err.emit();
|
||||
}
|
||||
|
||||
fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) {
|
||||
fn reject_shadowing_parameters(tcx: TyCtxt, def_id: DefId) {
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let parent = tcx.generics_of(generics.parent.unwrap());
|
||||
let impl_params: FxHashMap<_, _> = parent.types
|
||||
.iter()
|
||||
.map(|tp| (tp.name, tp.def_id))
|
||||
.collect();
|
||||
let impl_params: FxHashMap<_, _> =
|
||||
parent.params.iter()
|
||||
.flat_map(|param| {
|
||||
match param.kind {
|
||||
GenericParamDefKind::Lifetime => None,
|
||||
GenericParamDefKind::Type(_) => Some((param.name, param.def_id)),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
for method_param in &generics.types {
|
||||
for method_param in generics.params.iter() {
|
||||
match method_param.kind {
|
||||
// Shadowing is checked in resolve_lifetime.
|
||||
GenericParamDefKind::Lifetime => continue,
|
||||
_ => {},
|
||||
};
|
||||
if impl_params.contains_key(&method_param.name) {
|
||||
// Tighten up the span to focus on only the shadowing type
|
||||
let type_span = tcx.def_span(method_param.def_id);
|
||||
|
|
|
@ -181,7 +181,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
|
|||
self.tcx.at(span).type_param_predicates((self.item_def_id, def_id))
|
||||
}
|
||||
|
||||
fn re_infer(&self, _span: Span, _def: Option<&ty::RegionParameterDef>)
|
||||
fn re_infer(&self, _span: Span, _def: Option<&ty::GenericParamDef>)
|
||||
-> Option<ty::Region<'tcx>> {
|
||||
None
|
||||
}
|
||||
|
@ -243,8 +243,8 @@ fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
let param_owner = tcx.hir.ty_param_owner(param_id);
|
||||
let param_owner_def_id = tcx.hir.local_def_id(param_owner);
|
||||
let generics = tcx.generics_of(param_owner_def_id);
|
||||
let index = generics.type_param_to_index[&def_id];
|
||||
let ty = tcx.mk_param(index, tcx.hir.ty_param_name(param_id).as_interned_str());
|
||||
let index = generics.param_def_id_to_index[&def_id];
|
||||
let ty = tcx.mk_ty_param(index, tcx.hir.ty_param_name(param_id).as_interned_str());
|
||||
|
||||
// Don't look for bounds where the type parameter isn't in scope.
|
||||
let parent = if item_def_id == param_owner_def_id {
|
||||
|
@ -840,14 +840,16 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
// the node id for the Self type parameter.
|
||||
let param_id = item.id;
|
||||
|
||||
opt_self = Some(ty::TypeParameterDef {
|
||||
opt_self = Some(ty::GenericParamDef {
|
||||
index: 0,
|
||||
name: keywords::SelfType.name().as_interned_str(),
|
||||
def_id: tcx.hir.local_def_id(param_id),
|
||||
has_default: false,
|
||||
object_lifetime_default: rl::Set1::Empty,
|
||||
pure_wrt_drop: false,
|
||||
synthetic: None,
|
||||
kind: ty::GenericParamDefKind::Type(ty::TypeParamDef {
|
||||
has_default: false,
|
||||
object_lifetime_default: rl::Set1::Empty,
|
||||
synthetic: None,
|
||||
}),
|
||||
});
|
||||
|
||||
allow_defaults = true;
|
||||
|
@ -876,31 +878,33 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
let has_self = opt_self.is_some();
|
||||
let mut parent_has_self = false;
|
||||
let mut own_start = has_self as u32;
|
||||
let (parent_regions, parent_types) = parent_def_id.map_or((0, 0), |def_id| {
|
||||
let parent_count = parent_def_id.map_or(0, |def_id| {
|
||||
let generics = tcx.generics_of(def_id);
|
||||
assert_eq!(has_self, false);
|
||||
parent_has_self = generics.has_self;
|
||||
own_start = generics.count() as u32;
|
||||
(generics.parent_regions + generics.regions.len() as u32,
|
||||
generics.parent_types + generics.types.len() as u32)
|
||||
generics.parent_count + generics.params.len()
|
||||
});
|
||||
|
||||
let mut params: Vec<_> = opt_self.into_iter().collect();
|
||||
|
||||
let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics);
|
||||
let regions = early_lifetimes.enumerate().map(|(i, l)| {
|
||||
ty::RegionParameterDef {
|
||||
params.extend(early_lifetimes.enumerate().map(|(i, l)| {
|
||||
ty::GenericParamDef {
|
||||
name: l.lifetime.name.name().as_interned_str(),
|
||||
index: own_start + i as u32,
|
||||
def_id: tcx.hir.local_def_id(l.lifetime.id),
|
||||
pure_wrt_drop: l.pure_wrt_drop,
|
||||
kind: ty::GenericParamDefKind::Lifetime,
|
||||
}
|
||||
}).collect::<Vec<_>>();
|
||||
}));
|
||||
|
||||
let hir_id = tcx.hir.node_to_hir_id(node_id);
|
||||
let object_lifetime_defaults = tcx.object_lifetime_defaults(hir_id);
|
||||
|
||||
// Now create the real type parameters.
|
||||
let type_start = own_start + regions.len() as u32;
|
||||
let types = ast_generics.ty_params().enumerate().map(|(i, p)| {
|
||||
let type_start = own_start - has_self as u32 + params.len() as u32;
|
||||
params.extend(ast_generics.ty_params().enumerate().map(|(i, p)| {
|
||||
if p.name == keywords::SelfType.name() {
|
||||
span_bug!(p.span, "`Self` should not be the name of a regular parameter");
|
||||
}
|
||||
|
@ -916,19 +920,19 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
}
|
||||
}
|
||||
|
||||
ty::TypeParameterDef {
|
||||
ty::GenericParamDef {
|
||||
index: type_start + i as u32,
|
||||
name: p.name.as_interned_str(),
|
||||
def_id: tcx.hir.local_def_id(p.id),
|
||||
has_default: p.default.is_some(),
|
||||
object_lifetime_default:
|
||||
object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]),
|
||||
pure_wrt_drop: p.pure_wrt_drop,
|
||||
synthetic: p.synthetic,
|
||||
kind: ty::GenericParamDefKind::Type(ty::TypeParamDef {
|
||||
has_default: p.default.is_some(),
|
||||
object_lifetime_default:
|
||||
object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]),
|
||||
synthetic: p.synthetic,
|
||||
}),
|
||||
}
|
||||
});
|
||||
|
||||
let mut types: Vec<_> = opt_self.into_iter().chain(types).collect();
|
||||
}));
|
||||
|
||||
// provide junk type parameter defs - the only place that
|
||||
// cares about anything but the length is instantiation,
|
||||
|
@ -941,43 +945,45 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
};
|
||||
|
||||
for (i, &arg) in dummy_args.iter().enumerate() {
|
||||
types.push(ty::TypeParameterDef {
|
||||
params.push(ty::GenericParamDef {
|
||||
index: type_start + i as u32,
|
||||
name: Symbol::intern(arg).as_interned_str(),
|
||||
def_id,
|
||||
has_default: false,
|
||||
object_lifetime_default: rl::Set1::Empty,
|
||||
pure_wrt_drop: false,
|
||||
synthetic: None,
|
||||
kind: ty::GenericParamDefKind::Type(ty::TypeParamDef {
|
||||
has_default: false,
|
||||
object_lifetime_default: rl::Set1::Empty,
|
||||
synthetic: None,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
tcx.with_freevars(node_id, |fv| {
|
||||
types.extend(fv.iter().zip((dummy_args.len() as u32)..).map(|(_, i)| {
|
||||
ty::TypeParameterDef {
|
||||
params.extend(fv.iter().zip((dummy_args.len() as u32)..).map(|(_, i)| {
|
||||
ty::GenericParamDef {
|
||||
index: type_start + i,
|
||||
name: Symbol::intern("<upvar>").as_interned_str(),
|
||||
def_id,
|
||||
has_default: false,
|
||||
object_lifetime_default: rl::Set1::Empty,
|
||||
pure_wrt_drop: false,
|
||||
synthetic: None,
|
||||
kind: ty::GenericParamDefKind::Type(ty::TypeParamDef {
|
||||
has_default: false,
|
||||
object_lifetime_default: rl::Set1::Empty,
|
||||
synthetic: None,
|
||||
}),
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
let type_param_to_index = types.iter()
|
||||
.map(|param| (param.def_id, param.index))
|
||||
.collect();
|
||||
let param_def_id_to_index = params.iter()
|
||||
.map(|param| (param.def_id, param.index))
|
||||
.collect();
|
||||
|
||||
tcx.alloc_generics(ty::Generics {
|
||||
parent: parent_def_id,
|
||||
parent_regions,
|
||||
parent_types,
|
||||
regions,
|
||||
types,
|
||||
type_param_to_index,
|
||||
parent_count,
|
||||
params,
|
||||
param_def_id_to_index,
|
||||
has_self: has_self || parent_has_self,
|
||||
has_late_bound_regions: has_late_bound_regions(tcx, node),
|
||||
})
|
||||
|
@ -1090,15 +1096,7 @@ fn type_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
}
|
||||
|
||||
let substs = ty::ClosureSubsts {
|
||||
substs: Substs::for_item(
|
||||
tcx,
|
||||
def_id,
|
||||
|def, _| {
|
||||
let region = def.to_early_bound_region_data();
|
||||
tcx.mk_region(ty::ReEarlyBound(region))
|
||||
},
|
||||
|def, _| tcx.mk_param_from_def(def)
|
||||
)
|
||||
substs: Substs::identity_for_item(tcx, def_id),
|
||||
};
|
||||
|
||||
tcx.mk_closure(def_id, substs)
|
||||
|
@ -1390,7 +1388,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
};
|
||||
|
||||
let generics = tcx.generics_of(def_id);
|
||||
let parent_count = generics.parent_count() as u32;
|
||||
let parent_count = generics.parent_count as u32;
|
||||
let has_own_self = generics.has_self && parent_count == 0;
|
||||
|
||||
let mut predicates = vec![];
|
||||
|
|
|
@ -72,10 +72,9 @@ struct ImplWfCheck<'a, 'tcx: 'a> {
|
|||
impl<'a, 'tcx> ItemLikeVisitor<'tcx> for ImplWfCheck<'a, 'tcx> {
|
||||
fn visit_item(&mut self, item: &'tcx hir::Item) {
|
||||
match item.node {
|
||||
hir::ItemImpl(.., ref generics, _, _, ref impl_item_refs) => {
|
||||
hir::ItemImpl(.., ref impl_item_refs) => {
|
||||
let impl_def_id = self.tcx.hir.local_def_id(item.id);
|
||||
enforce_impl_params_are_constrained(self.tcx,
|
||||
generics,
|
||||
impl_def_id,
|
||||
impl_item_refs);
|
||||
enforce_impl_items_are_distinct(self.tcx, impl_item_refs);
|
||||
|
@ -90,7 +89,6 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for ImplWfCheck<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
impl_hir_generics: &hir::Generics,
|
||||
impl_def_id: DefId,
|
||||
impl_item_refs: &[hir::ImplItemRef])
|
||||
{
|
||||
|
@ -104,17 +102,9 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
ctp::identify_constrained_type_params(
|
||||
tcx, &impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters);
|
||||
|
||||
// Disallow ANY unconstrained type parameters.
|
||||
for (ty_param, param) in impl_generics.types.iter().zip(impl_hir_generics.ty_params()) {
|
||||
let param_ty = ty::ParamTy::for_def(ty_param);
|
||||
if !input_parameters.contains(&ctp::Parameter::from(param_ty)) {
|
||||
report_unused_parameter(tcx, param.span, "type", ¶m_ty.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
// Disallow unconstrained lifetimes, but only if they appear in assoc types.
|
||||
let lifetimes_in_associated_types: FxHashSet<_> = impl_item_refs.iter()
|
||||
.map(|item_ref| tcx.hir.local_def_id(item_ref.id.node_id))
|
||||
.map(|item_ref| tcx.hir.local_def_id(item_ref.id.node_id))
|
||||
.filter(|&def_id| {
|
||||
let item = tcx.associated_item(def_id);
|
||||
item.kind == ty::AssociatedKind::Type && item.defaultness.has_value()
|
||||
|
@ -122,17 +112,29 @@ fn enforce_impl_params_are_constrained<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
.flat_map(|def_id| {
|
||||
ctp::parameters_for(&tcx.type_of(def_id), true)
|
||||
}).collect();
|
||||
for (ty_lifetime, lifetime) in impl_generics.regions.iter()
|
||||
.zip(impl_hir_generics.lifetimes())
|
||||
{
|
||||
let param = ctp::Parameter::from(ty_lifetime.to_early_bound_region_data());
|
||||
|
||||
if
|
||||
lifetimes_in_associated_types.contains(¶m) && // (*)
|
||||
!input_parameters.contains(¶m)
|
||||
{
|
||||
report_unused_parameter(tcx, lifetime.lifetime.span,
|
||||
"lifetime", &lifetime.lifetime.name.name().to_string());
|
||||
for param in &impl_generics.params {
|
||||
match param.kind {
|
||||
// Disallow ANY unconstrained type parameters.
|
||||
ty::GenericParamDefKind::Type(_) => {
|
||||
let param_ty = ty::ParamTy::for_def(param);
|
||||
if !input_parameters.contains(&ctp::Parameter::from(param_ty)) {
|
||||
report_unused_parameter(tcx,
|
||||
tcx.def_span(param.def_id),
|
||||
"type",
|
||||
¶m_ty.to_string());
|
||||
}
|
||||
}
|
||||
ty::GenericParamDefKind::Lifetime => {
|
||||
let param_lt = ctp::Parameter::from(param.to_early_bound_region_data());
|
||||
if lifetimes_in_associated_types.contains(¶m_lt) && // (*)
|
||||
!input_parameters.contains(¶m_lt) {
|
||||
report_unused_parameter(tcx,
|
||||
tcx.def_span(param.def_id),
|
||||
"lifetime",
|
||||
¶m.name.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -353,7 +353,7 @@ fn insert_outlives_predicate<'tcx>(
|
|||
// Vec<U>`. Decomposing `Vec<U>` into
|
||||
// components would yield `U`, and we add the
|
||||
// where clause that `U: 'a`.
|
||||
let ty: Ty<'tcx> = tcx.mk_param(param_ty.idx, param_ty.name);
|
||||
let ty: Ty<'tcx> = tcx.mk_ty_param(param_ty.idx, param_ty.name);
|
||||
required_predicates
|
||||
.insert(ty::OutlivesPredicate(ty.into(), outlived_region));
|
||||
}
|
||||
|
|
|
@ -224,42 +224,39 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
}
|
||||
|
||||
fn generics_to_path_params(&self, generics: ty::Generics) -> hir::PathParameters {
|
||||
let lifetimes = HirVec::from_vec(
|
||||
generics
|
||||
.regions
|
||||
.iter()
|
||||
.map(|p| {
|
||||
let name = if p.name == "" {
|
||||
let mut lifetimes = vec![];
|
||||
let mut types = vec![];
|
||||
|
||||
for param in generics.params.iter() {
|
||||
match param.kind {
|
||||
ty::GenericParamDefKind::Lifetime => {
|
||||
let name = if param.name == "" {
|
||||
hir::LifetimeName::Static
|
||||
} else {
|
||||
hir::LifetimeName::Name(p.name.as_symbol())
|
||||
hir::LifetimeName::Name(param.name.as_symbol())
|
||||
};
|
||||
|
||||
hir::Lifetime {
|
||||
lifetimes.push(hir::Lifetime {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: DUMMY_SP,
|
||||
name,
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
let types = HirVec::from_vec(
|
||||
generics
|
||||
.types
|
||||
.iter()
|
||||
.map(|p| P(self.ty_param_to_ty(p.clone())))
|
||||
.collect(),
|
||||
);
|
||||
});
|
||||
}
|
||||
ty::GenericParamDefKind::Type(_) => {
|
||||
types.push(P(self.ty_param_to_ty(param.clone())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hir::PathParameters {
|
||||
lifetimes: lifetimes,
|
||||
types: types,
|
||||
lifetimes: HirVec::from_vec(lifetimes),
|
||||
types: HirVec::from_vec(types),
|
||||
bindings: HirVec::new(),
|
||||
parenthesized: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_param_to_ty(&self, param: ty::TypeParameterDef) -> hir::Ty {
|
||||
fn ty_param_to_ty(&self, param: ty::GenericParamDef) -> hir::Ty {
|
||||
debug!("ty_param_to_ty({:?}) {:?}", param, param.def_id);
|
||||
hir::Ty {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
|
@ -494,7 +491,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
&self,
|
||||
tcx: TyCtxt<'b, 'c, 'd>,
|
||||
pred: ty::Predicate<'d>,
|
||||
) -> FxHashSet<GenericParam> {
|
||||
) -> FxHashSet<GenericParamDef> {
|
||||
pred.walk_tys()
|
||||
.flat_map(|t| {
|
||||
let mut regions = FxHashSet();
|
||||
|
@ -505,7 +502,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
// We only care about late bound regions, as we need to add them
|
||||
// to the 'for<>' section
|
||||
&ty::ReLateBound(_, ty::BoundRegion::BrNamed(_, name)) => {
|
||||
Some(GenericParam::Lifetime(Lifetime(name.to_string())))
|
||||
Some(GenericParamDef::Lifetime(Lifetime(name.to_string())))
|
||||
}
|
||||
&ty::ReVar(_) | &ty::ReEarlyBound(_) => None,
|
||||
_ => panic!("Unexpected region type {:?}", r),
|
||||
|
@ -853,7 +850,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
|
||||
for p in generic_params.iter_mut() {
|
||||
match p {
|
||||
&mut GenericParam::Type(ref mut ty) => {
|
||||
&mut GenericParamDef::Type(ref mut ty) => {
|
||||
// We never want something like 'impl<T=Foo>'
|
||||
ty.default.take();
|
||||
|
||||
|
@ -863,7 +860,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
|
|||
ty.bounds.insert(0, TyParamBound::maybe_sized(self.cx));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
GenericParamDef::Lifetime(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ use rustc::hir::def::{self, Def, CtorKind};
|
|||
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
use rustc::hir::def_id::DefIndexAddressSpace;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind};
|
||||
use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind, GenericParamCount};
|
||||
use rustc::middle::stability;
|
||||
use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
||||
use rustc_typeck::hir_ty_to_ty;
|
||||
|
@ -1336,14 +1336,18 @@ impl Clean<TyParam> for hir::TyParam {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<TyParam> for ty::TypeParameterDef {
|
||||
impl<'tcx> Clean<TyParam> for ty::GenericParamDef {
|
||||
fn clean(&self, cx: &DocContext) -> TyParam {
|
||||
cx.renderinfo.borrow_mut().external_typarams.insert(self.def_id, self.name.clean(cx));
|
||||
let has_default = match self.kind {
|
||||
ty::GenericParamDefKind::Type(ty) => ty.has_default,
|
||||
_ => panic!("tried to convert a non-type GenericParamDef as a type")
|
||||
};
|
||||
TyParam {
|
||||
name: self.name.clean(cx),
|
||||
did: self.def_id,
|
||||
bounds: vec![], // these are filled in from the where-clauses
|
||||
default: if self.has_default {
|
||||
default: if has_default {
|
||||
Some(cx.tcx.type_of(self.def_id).clean(cx))
|
||||
} else {
|
||||
None
|
||||
|
@ -1484,7 +1488,7 @@ impl<'a, 'tcx> Clean<TyParamBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>
|
|||
if let &ty::RegionKind::ReLateBound(..) = *reg {
|
||||
debug!(" hit an ReLateBound {:?}", reg);
|
||||
if let Some(lt) = reg.clean(cx) {
|
||||
late_bounds.push(GenericParam::Lifetime(lt));
|
||||
late_bounds.push(GenericParamDef::Lifetime(lt));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1577,8 +1581,8 @@ impl Clean<Lifetime> for hir::LifetimeDef {
|
|||
}
|
||||
}
|
||||
|
||||
impl Clean<Lifetime> for ty::RegionParameterDef {
|
||||
fn clean(&self, _: &DocContext) -> Lifetime {
|
||||
impl<'tcx> Clean<Lifetime> for ty::GenericParamDef {
|
||||
fn clean(&self, _cx: &DocContext) -> Lifetime {
|
||||
Lifetime(self.name.to_string())
|
||||
}
|
||||
}
|
||||
|
@ -1718,26 +1722,25 @@ impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
|
|||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum GenericParam {
|
||||
pub enum GenericParamDef {
|
||||
Lifetime(Lifetime),
|
||||
Type(TyParam),
|
||||
}
|
||||
|
||||
impl GenericParam {
|
||||
impl GenericParamDef {
|
||||
pub fn is_synthetic_type_param(&self) -> bool {
|
||||
if let GenericParam::Type(ref t) = *self {
|
||||
t.synthetic.is_some()
|
||||
} else {
|
||||
false
|
||||
match self {
|
||||
GenericParamDef::Type(ty) => ty.synthetic.is_some(),
|
||||
GenericParamDef::Lifetime(_) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clean<GenericParam> for hir::GenericParam {
|
||||
fn clean(&self, cx: &DocContext) -> GenericParam {
|
||||
impl Clean<GenericParamDef> for hir::GenericParam {
|
||||
fn clean(&self, cx: &DocContext) -> GenericParamDef {
|
||||
match *self {
|
||||
hir::GenericParam::Lifetime(ref l) => GenericParam::Lifetime(l.clean(cx)),
|
||||
hir::GenericParam::Type(ref t) => GenericParam::Type(t.clean(cx)),
|
||||
hir::GenericParam::Lifetime(ref l) => GenericParamDef::Lifetime(l.clean(cx)),
|
||||
hir::GenericParam::Type(ref t) => GenericParamDef::Type(t.clean(cx)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1745,7 +1748,7 @@ impl Clean<GenericParam> for hir::GenericParam {
|
|||
// maybe use a Generic enum and use Vec<Generic>?
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Default, Hash)]
|
||||
pub struct Generics {
|
||||
pub params: Vec<GenericParam>,
|
||||
pub params: Vec<GenericParamDef>,
|
||||
pub where_predicates: Vec<WherePredicate>,
|
||||
}
|
||||
|
||||
|
@ -1754,7 +1757,7 @@ impl Clean<Generics> for hir::Generics {
|
|||
let mut params = Vec::with_capacity(self.params.len());
|
||||
for p in &self.params {
|
||||
let p = p.clean(cx);
|
||||
if let GenericParam::Type(ref tp) = p {
|
||||
if let GenericParamDef::Type(ref tp) = p {
|
||||
if tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) {
|
||||
cx.impl_trait_bounds.borrow_mut().insert(tp.did, tp.bounds.clone());
|
||||
}
|
||||
|
@ -1774,7 +1777,7 @@ impl Clean<Generics> for hir::Generics {
|
|||
WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => {
|
||||
if bounds.is_empty() {
|
||||
for param in &mut g.params {
|
||||
if let GenericParam::Type(ref mut type_param) = *param {
|
||||
if let GenericParamDef::Type(ref mut type_param) = *param {
|
||||
if &type_param.name == name {
|
||||
mem::swap(bounds, &mut type_param.bounds);
|
||||
break
|
||||
|
@ -1800,14 +1803,18 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
|
|||
// Bounds in the type_params and lifetimes fields are repeated in the
|
||||
// predicates field (see rustc_typeck::collect::ty_generics), so remove
|
||||
// them.
|
||||
let stripped_typarams = gens.types.iter().filter_map(|tp| {
|
||||
if tp.name == keywords::SelfType.name().as_str() {
|
||||
assert_eq!(tp.index, 0);
|
||||
None
|
||||
let stripped_typarams = gens.params.iter().filter_map(|param| {
|
||||
if let ty::GenericParamDefKind::Type(_) = param.kind {
|
||||
if param.name == keywords::SelfType.name().as_str() {
|
||||
assert_eq!(param.index, 0);
|
||||
None
|
||||
} else {
|
||||
Some(param.clean(cx))
|
||||
}
|
||||
} else {
|
||||
Some(tp.clean(cx))
|
||||
None
|
||||
}
|
||||
}).collect::<Vec<_>>();
|
||||
}).collect::<Vec<TyParam>>();
|
||||
|
||||
let mut where_predicates = preds.predicates.to_vec().clean(cx);
|
||||
|
||||
|
@ -1849,16 +1856,20 @@ impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics,
|
|||
// and instead see `where T: Foo + Bar + Sized + 'a`
|
||||
|
||||
Generics {
|
||||
params: gens.regions
|
||||
.clean(cx)
|
||||
.into_iter()
|
||||
.map(|lp| GenericParam::Lifetime(lp))
|
||||
.chain(
|
||||
simplify::ty_params(stripped_typarams)
|
||||
.into_iter()
|
||||
.map(|tp| GenericParam::Type(tp))
|
||||
)
|
||||
.collect(),
|
||||
params: gens.params
|
||||
.iter()
|
||||
.flat_map(|param| {
|
||||
if let ty::GenericParamDefKind::Lifetime = param.kind {
|
||||
Some(GenericParamDef::Lifetime(param.clean(cx)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).chain(
|
||||
simplify::ty_params(stripped_typarams)
|
||||
.into_iter()
|
||||
.map(|tp| GenericParamDef::Type(tp))
|
||||
)
|
||||
.collect(),
|
||||
where_predicates: simplify::where_clauses(cx, where_predicates),
|
||||
}
|
||||
}
|
||||
|
@ -2349,7 +2360,7 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
|
|||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct PolyTrait {
|
||||
pub trait_: Type,
|
||||
pub generic_params: Vec<GenericParam>,
|
||||
pub generic_params: Vec<GenericParamDef>,
|
||||
}
|
||||
|
||||
/// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
|
||||
|
@ -2676,20 +2687,34 @@ impl Clean<Type> for hir::Ty {
|
|||
let mut ty_substs = FxHashMap();
|
||||
let mut lt_substs = FxHashMap();
|
||||
provided_params.with_parameters(|provided_params| {
|
||||
for (i, ty_param) in generics.ty_params().enumerate() {
|
||||
let ty_param_def = Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id));
|
||||
if let Some(ty) = provided_params.types.get(i).cloned() {
|
||||
ty_substs.insert(ty_param_def, ty.into_inner().clean(cx));
|
||||
} else if let Some(default) = ty_param.default.clone() {
|
||||
ty_substs.insert(ty_param_def, default.into_inner().clean(cx));
|
||||
}
|
||||
}
|
||||
|
||||
for (i, lt_param) in generics.lifetimes().enumerate() {
|
||||
if let Some(lt) = provided_params.lifetimes.get(i).cloned() {
|
||||
if !lt.is_elided() {
|
||||
let lt_def_id = cx.tcx.hir.local_def_id(lt_param.lifetime.id);
|
||||
lt_substs.insert(lt_def_id, lt.clean(cx));
|
||||
let mut indices = GenericParamCount {
|
||||
lifetimes: 0,
|
||||
types: 0
|
||||
};
|
||||
for param in generics.params.iter() {
|
||||
match param {
|
||||
hir::GenericParam::Lifetime(lt_param) => {
|
||||
if let Some(lt) = provided_params.lifetimes
|
||||
.get(indices.lifetimes).cloned() {
|
||||
if !lt.is_elided() {
|
||||
let lt_def_id =
|
||||
cx.tcx.hir.local_def_id(lt_param.lifetime.id);
|
||||
lt_substs.insert(lt_def_id, lt.clean(cx));
|
||||
}
|
||||
}
|
||||
indices.lifetimes += 1;
|
||||
}
|
||||
hir::GenericParam::Type(ty_param) => {
|
||||
let ty_param_def =
|
||||
Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id));
|
||||
if let Some(ty) = provided_params.types
|
||||
.get(indices.types).cloned() {
|
||||
ty_substs.insert(ty_param_def, ty.into_inner().clean(cx));
|
||||
} else if let Some(default) = ty_param.default.clone() {
|
||||
ty_substs.insert(ty_param_def,
|
||||
default.into_inner().clean(cx));
|
||||
}
|
||||
indices.types += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3425,7 +3450,7 @@ impl Clean<Item> for doctree::Typedef {
|
|||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct BareFunctionDecl {
|
||||
pub unsafety: hir::Unsafety,
|
||||
pub generic_params: Vec<GenericParam>,
|
||||
pub generic_params: Vec<GenericParamDef>,
|
||||
pub decl: FnDecl,
|
||||
pub abi: Abi,
|
||||
}
|
||||
|
@ -4184,7 +4209,7 @@ struct RegionDeps<'tcx> {
|
|||
#[derive(Eq, PartialEq, Hash, Debug)]
|
||||
enum SimpleBound {
|
||||
RegionBound(Lifetime),
|
||||
TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParam>, hir::TraitBoundModifier)
|
||||
TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier)
|
||||
}
|
||||
|
||||
enum AutoTraitResult {
|
||||
|
|
|
@ -117,11 +117,11 @@ impl<'a> fmt::Display for TyParamBounds<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for clean::GenericParam {
|
||||
impl fmt::Display for clean::GenericParamDef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
clean::GenericParam::Lifetime(ref lp) => write!(f, "{}", lp),
|
||||
clean::GenericParam::Type(ref tp) => {
|
||||
clean::GenericParamDef::Lifetime(ref lp) => write!(f, "{}", lp),
|
||||
clean::GenericParamDef::Type(ref tp) => {
|
||||
f.write_str(&tp.name)?;
|
||||
|
||||
if !tp.bounds.is_empty() {
|
||||
|
|
|
@ -1453,8 +1453,11 @@ impl DocFolder for Cache {
|
|||
impl<'a> Cache {
|
||||
fn generics(&mut self, generics: &clean::Generics) {
|
||||
for param in &generics.params {
|
||||
if let clean::GenericParam::Type(ref typ) = *param {
|
||||
self.typarams.insert(typ.did, typ.name.clone());
|
||||
match *param {
|
||||
clean::GenericParamDef::Type(ref typ) => {
|
||||
self.typarams.insert(typ.did, typ.name.clone());
|
||||
}
|
||||
clean::GenericParamDef::Lifetime(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ trait BadAnnotation1
|
|||
{}
|
||||
|
||||
#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
|
||||
//~^ ERROR there is no type parameter C on trait BadAnnotation2
|
||||
//~^ ERROR there is no parameter C on trait BadAnnotation2
|
||||
trait BadAnnotation2<A,B>
|
||||
{}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ LL | #[rustc_on_unimplemented] //~ ERROR `#[rustc_on_unimplemented]` requires a
|
|||
|
|
||||
= note: eg `#[rustc_on_unimplemented = "foo"]`
|
||||
|
||||
error[E0230]: there is no type parameter C on trait BadAnnotation2
|
||||
error[E0230]: there is no parameter C on trait BadAnnotation2
|
||||
--> $DIR/bad-annotation.rs:30:1
|
||||
|
|
||||
LL | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue