use crate::namespace::Namespace;
use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
use rustc::traits;
-use rustc::ty::{self, DefIdTree, Ty, TyCtxt, ToPredicate, TypeFoldable};
+use rustc::ty::{self, DefIdTree, Ty, TyCtxt, Const, ToPredicate, TypeFoldable};
use rustc::ty::{GenericParamDef, GenericParamDefKind};
use rustc::ty::subst::{Kind, Subst, InternalSubsts, SubstsRef};
use rustc::ty::wf::object_region_bounds;
pub struct PathSeg(pub DefId, pub usize);
pub trait AstConv<'gcx, 'tcx> {
- fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>;
+ fn tcx<'a>(&'a self) -> TyCtxt<'gcx, 'tcx>;
/// Returns the set of bounds in scope for the type parameter with
/// the given id.
-> &'tcx ty::GenericPredicates<'tcx>;
/// Returns the lifetime to use when a lifetime is omitted (and not elided).
- fn re_infer(&self, span: Span, _def: Option<&ty::GenericParamDef>)
+ fn re_infer(
+ &self,
+ param: Option<&ty::GenericParamDef>,
+ span: Span,
+ )
-> Option<ty::Region<'tcx>>;
/// Returns the type to use when a type is omitted.
- fn ty_infer(&self, span: Span) -> Ty<'tcx>;
+ fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>;
- /// Same as `ty_infer`, but with a known type parameter definition.
- fn ty_infer_for_def(&self,
- _def: &ty::GenericParamDef,
- span: Span) -> Ty<'tcx> {
- self.ty_infer(span)
- }
+ /// Returns the const to use when a const is omitted.
+ fn ct_infer(
+ &self,
+ ty: Ty<'tcx>,
+ param: Option<&ty::GenericParamDef>,
+ span: Span,
+ ) -> &'tcx Const<'tcx>;
/// Projecting an associated type from a (potentially)
/// higher-ranked trait reference is more complicated, because of
}
None => {
- self.re_infer(lifetime.span, def)
+ self.re_infer(def, lifetime.span)
.unwrap_or_else(|| {
// This indicates an illegal lifetime
// elision. `resolve_lifetime` should have
span,
def_id,
generic_args,
- item_segment.infer_types,
+ item_segment.infer_args,
None,
)
});
/// Report error if there is an explicit type parameter when using `impl Trait`.
fn check_impl_trait(
- tcx: TyCtxt<'_, '_, '_>,
+ tcx: TyCtxt<'_, '_>,
span: Span,
seg: &hir::PathSegment,
generics: &ty::Generics,
) -> bool {
- let explicit = !seg.infer_types;
+ let explicit = !seg.infer_args;
let impl_trait = generics.params.iter().any(|param| match param.kind {
ty::GenericParamDefKind::Type {
synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), ..
/// Checks that the correct number of generic arguments have been provided.
/// Used specifically for function calls.
pub fn check_generic_arg_count_for_call(
- tcx: TyCtxt<'_, '_, '_>,
+ tcx: TyCtxt<'_, '_>,
span: Span,
def: &ty::Generics,
seg: &hir::PathSegment,
GenericArgPosition::Value
},
def.parent.is_none() && def.has_self, // `has_self`
- seg.infer_types || suppress_mismatch, // `infer_types`
+ seg.infer_args || suppress_mismatch, // `infer_args`
).0
}
/// Checks that the correct number of generic arguments have been provided.
/// This is used both for datatypes and function calls.
fn check_generic_arg_count(
- tcx: TyCtxt<'_, '_, '_>,
+ tcx: TyCtxt<'_, '_>,
span: Span,
def: &ty::Generics,
args: &hir::GenericArgs,
position: GenericArgPosition,
has_self: bool,
- infer_types: bool,
+ infer_args: bool,
) -> (bool, Option<Vec<Span>>) {
// At this stage we are guaranteed that the generic arguments are in the correct order, e.g.
// that lifetimes will proceed types. So it suffices to check the number of each generic
let param_counts = def.own_counts();
let arg_counts = args.own_counts();
let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0;
- let infer_consts = position != GenericArgPosition::Type && arg_counts.consts == 0;
let mut defaults: ty::GenericParamCount = Default::default();
for param in &def.params {
offset
);
// We enforce the following: `required` <= `provided` <= `permitted`.
- // For kinds without defaults (i.e., lifetimes), `required == permitted`.
+ // For kinds without defaults (e.g.., lifetimes), `required == permitted`.
// For other kinds (i.e., types), `permitted` may be greater than `required`.
if required <= provided && provided <= permitted {
return (reported_late_bound_region_err.unwrap_or(false), None);
);
}
// FIXME(const_generics:defaults)
- if !infer_consts || arg_counts.consts > param_counts.consts {
+ if !infer_args || arg_counts.consts > param_counts.consts {
check_kind_count(
"const",
param_counts.consts,
);
}
// Note that type errors are currently be emitted *after* const errors.
- if !infer_types
+ if !infer_args
|| arg_counts.types > param_counts.types - defaults.types - has_self as usize {
check_kind_count(
"type",
/// instantiate a `Kind`.
/// - `inferred_kind`: if no parameter was provided, and inference is enabled, then
/// creates a suitable inference variable.
- pub fn create_substs_for_generic_args<'a, 'b>(
- tcx: TyCtxt<'a, 'gcx, 'tcx>,
+ pub fn create_substs_for_generic_args<'b>(
+ tcx: TyCtxt<'gcx, 'tcx>,
def_id: DefId,
parent_substs: &[Kind<'tcx>],
has_self: bool,
}
// Check whether this segment takes generic arguments and the user has provided any.
- let (generic_args, infer_types) = args_for_def_id(def_id);
+ let (generic_args, infer_args) = args_for_def_id(def_id);
let mut args = generic_args.iter().flat_map(|generic_args| generic_args.args.iter())
.peekable();
| (GenericArg::Const(_), GenericParamDefKind::Lifetime) => {
// We expected a lifetime argument, but got a type or const
// argument. That means we're inferring the lifetimes.
- substs.push(inferred_kind(None, param, infer_types));
+ substs.push(inferred_kind(None, param, infer_args));
params.next();
}
(_, _) => {
(None, Some(¶m)) => {
// If there are fewer arguments than parameters, it means
// we're inferring the remaining arguments.
- substs.push(inferred_kind(Some(&substs), param, infer_types));
+ substs.push(inferred_kind(Some(&substs), param, infer_args));
args.next();
params.next();
}
span: Span,
def_id: DefId,
generic_args: &'a hir::GenericArgs,
- infer_types: bool,
+ infer_args: bool,
self_ty: Option<Ty<'tcx>>)
-> (SubstsRef<'tcx>, Vec<ConvertedBinding<'tcx>>, Option<Vec<Span>>)
{
&generic_args,
GenericArgPosition::Type,
has_self,
- infer_types,
+ infer_args,
);
let is_object = self_ty.map_or(false, |ty| {
self_ty.is_some(),
self_ty,
// Provide the generic args, and whether types should be inferred.
- |_| (Some(generic_args), infer_types),
+ |_| (Some(generic_args), infer_args),
// Provide substitutions for parameters for which (valid) arguments have been provided.
|param, arg| {
match (¶m.kind, arg) {
}
},
// Provide substitutions for parameters for which arguments are inferred.
- |substs, param, infer_types| {
+ |substs, param, infer_args| {
match param.kind {
GenericParamDefKind::Lifetime => tcx.lifetimes.re_static.into(),
GenericParamDefKind::Type { has_default, .. } => {
- if !infer_types && has_default {
+ if !infer_args && has_default {
// No type parameter provided, but a default exists.
// If we are converting an object type, then the
.subst_spanned(tcx, substs.unwrap(), Some(span))
).into()
}
- } else if infer_types {
+ } else if infer_args {
// No type parameters were provided, we can infer all.
- if !default_needs_object_self(param) {
- self.ty_infer_for_def(param, span).into()
+ let param = if !default_needs_object_self(param) {
+ Some(param)
} else {
- self.ty_infer(span).into()
- }
+ None
+ };
+ self.ty_infer(param, span).into()
} else {
// We've already errored above about the mismatch.
tcx.types.err.into()
}
GenericParamDefKind::Const => {
// FIXME(const_generics:defaults)
- // We've already errored above about the mismatch.
- tcx.consts.err.into()
+ if infer_args {
+ // No const parameters were provided, we can infer all.
+ let ty = tcx.at(span).type_of(param.def_id);
+ self.ct_infer(ty, Some(param), span).into()
+ } else {
+ // We've already errored above about the mismatch.
+ tcx.consts.err.into()
+ }
}
}
},
self.create_substs_for_ast_path(span,
trait_def_id,
generic_args,
- trait_segment.infer_types,
+ trait_segment.infer_args,
Some(self_ty))
})
}
if tcx.named_region(lifetime.hir_id).is_some() {
self.ast_region_to_region(lifetime, None)
} else {
- self.re_infer(span, None).unwrap_or_else(|| {
+ self.re_infer(None, span).unwrap_or_else(|| {
span_err!(tcx.sess, span, E0228,
"the lifetime bound for this object type cannot be deduced \
from context; please supply an explicit bound");
has_err
}
- pub fn prohibit_assoc_ty_binding(tcx: TyCtxt<'_, '_, '_>, span: Span) {
+ pub fn prohibit_assoc_ty_binding(tcx: TyCtxt<'_, '_>, span: Span) {
let mut err = struct_span_err!(tcx.sess, span, E0229,
"associated type bindings are not allowed here");
err.span_label(span, "associated type not allowed here").emit();
// values in a ExprKind::Closure, or as
// the type of local variables. Both of these cases are
// handled specially and will not descend into this routine.
- self.ty_infer(ast_ty.span)
+ self.ty_infer(None, ast_ty.span)
}
hir::TyKind::CVarArgs(lt) => {
let va_list_did = match tcx.lang_items().va_list() {
result_ty
}
+ /// Returns the `DefId` of the constant parameter that the provided expression is a path to.
+ pub fn const_param_def_id(&self, expr: &hir::Expr) -> Option<DefId> {
+ match &expr.node {
+ ExprKind::Path(hir::QPath::Resolved(_, path)) => match path.res {
+ Res::Def(DefKind::ConstParam, did) => Some(did),
+ _ => None,
+ },
+ _ => None,
+ }
+ }
+
pub fn ast_const_to_const(
&self,
ast_const: &hir::AnonConst,
}
}
- if let ExprKind::Path(ref qpath) = expr.node {
- if let hir::QPath::Resolved(_, ref path) = qpath {
- if let Res::Def(DefKind::ConstParam, def_id) = path.res {
- let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
- 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.param_def_id_to_index[&tcx.hir().local_def_id(node_id)];
- let name = tcx.hir().name(node_id).as_interned_str();
- const_.val = ConstValue::Param(ty::ParamConst::new(index, name));
- }
- }
- };
+ if let Some(def_id) = self.const_param_def_id(expr) {
+ // Find the name and index of the const parameter by indexing the generics of the
+ // parent item and construct a `ParamConst`.
+ let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
+ 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.param_def_id_to_index[&tcx.hir().local_def_id(node_id)];
+ let name = tcx.hir().name(node_id).as_interned_str();
+ const_.val = ConstValue::Param(ty::ParamConst::new(index, name));
+ }
tcx.mk_const(const_)
}
pub implicitly_sized: Option<Span>,
}
-impl<'a, 'gcx, 'tcx> Bounds<'tcx> {
+impl<'gcx, 'tcx> Bounds<'tcx> {
/// Converts a bounds list into a flat set of predicates (like
/// where-clauses). Because some of our bounds listings (e.g.,
/// regions) don't include the self-type, you must supply the
/// self-type here (the `param_ty` parameter).
- pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, param_ty: Ty<'tcx>)
- -> Vec<(ty::Predicate<'tcx>, Span)>
- {
+ pub fn predicates(
+ &self,
+ tcx: TyCtxt<'gcx, 'tcx>,
+ param_ty: Ty<'tcx>,
+ ) -> Vec<(ty::Predicate<'tcx>, Span)> {
// If it could be sized, and is, add the `Sized` predicate.
let sized_predicate = self.implicitly_sized.and_then(|span| {
tcx.lang_items().sized_trait().map(|sized| {