X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flibrustc_typeck%2Fastconv.rs;h=2c9309a1696cfd65210643a491bcb1470caffac1;hb=fff08cb04389497d254fb40948674cbbee402908;hp=34f817ba570e705d4a7809e95844537e2a5666c0;hpb=991c719a1d0f95c37ed7ea56bdb38bcc2a6246b9;p=rust.git diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 34f817ba570..2c9309a1696 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -13,7 +13,7 @@ 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; @@ -41,7 +41,7 @@ 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. @@ -49,18 +49,23 @@ fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> &'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>; /// 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 @@ -156,7 +161,7 @@ pub fn ast_region_to_region(&self, } 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 @@ -191,7 +196,7 @@ pub fn ast_path_substs_for_ty(&self, span, def_id, generic_args, - item_segment.infer_types, + item_segment.infer_args, None, ) }); @@ -203,12 +208,12 @@ pub fn ast_path_substs_for_ty(&self, /// 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), .. @@ -234,7 +239,7 @@ fn check_impl_trait( /// 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, @@ -259,20 +264,20 @@ pub fn check_generic_arg_count_for_call( 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>) { // 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 @@ -280,7 +285,6 @@ fn check_generic_arg_count( 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 { @@ -333,7 +337,7 @@ fn check_generic_arg_count( 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); @@ -404,7 +408,7 @@ fn check_generic_arg_count( ); } // 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, @@ -414,7 +418,7 @@ fn check_generic_arg_count( ); } // 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", @@ -457,8 +461,8 @@ fn check_generic_arg_count( /// 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, @@ -511,7 +515,7 @@ pub fn create_substs_for_generic_args<'a, 'b>( } // 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(); @@ -535,7 +539,7 @@ pub fn create_substs_for_generic_args<'a, 'b>( | (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(); } (_, _) => { @@ -556,7 +560,7 @@ pub fn create_substs_for_generic_args<'a, 'b>( (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(); } @@ -592,7 +596,7 @@ fn create_substs_for_ast_path<'a>(&self, span: Span, def_id: DefId, generic_args: &'a hir::GenericArgs, - infer_types: bool, + infer_args: bool, self_ty: Option>) -> (SubstsRef<'tcx>, Vec>, Option>) { @@ -617,7 +621,7 @@ fn create_substs_for_ast_path<'a>(&self, &generic_args, GenericArgPosition::Type, has_self, - infer_types, + infer_args, ); let is_object = self_ty.map_or(false, |ty| { @@ -644,7 +648,7 @@ fn create_substs_for_ast_path<'a>(&self, 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) { @@ -661,11 +665,11 @@ fn create_substs_for_ast_path<'a>(&self, } }, // 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 @@ -693,13 +697,14 @@ fn create_substs_for_ast_path<'a>(&self, .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() @@ -707,8 +712,14 @@ fn create_substs_for_ast_path<'a>(&self, } 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() + } } } }, @@ -880,7 +891,7 @@ fn create_substs_for_ast_trait_ref( self.create_substs_for_ast_path(span, trait_def_id, generic_args, - trait_segment.infer_types, + trait_segment.infer_args, Some(self_ty)) }) } @@ -1428,7 +1439,7 @@ fn conv_object_ty_poly_trait_ref(&self, 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"); @@ -1799,7 +1810,7 @@ pub fn prohibit_generics<'a, T: IntoIterator>( 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(); @@ -2122,7 +2133,7 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> { // 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() { @@ -2144,6 +2155,17 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> { 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 { + 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, @@ -2174,19 +2196,17 @@ pub fn ast_const_to_const( } } - 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_) } @@ -2395,14 +2415,16 @@ pub struct Bounds<'tcx> { pub implicitly_sized: Option, } -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| {