X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Flibrustc_typeck%2Fastconv.rs;h=2c9309a1696cfd65210643a491bcb1470caffac1;hb=fff08cb04389497d254fb40948674cbbee402908;hp=cc054adee7bea80ebe5b72923b5357f755f78027;hpb=28ce2b1fdb53562ab3ed4e3b1f6b62a57c68f3e9;p=rust.git diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index cc054adee7b..2c9309a1696 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -8,11 +8,12 @@ use crate::hir::def_id::DefId; use crate::hir::HirVec; use crate::lint; +use crate::middle::lang_items::SizedTraitLangItem; use crate::middle::resolve_lifetime as rl; 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; @@ -40,26 +41,31 @@ 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. fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> &'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::GenericParamDef>) + /// Returns the lifetime to use when a lifetime is omitted (and not elided). + fn re_infer( + &self, + param: Option<&ty::GenericParamDef>, + span: Span, + ) -> Option>; - /// What type should we use when a type is omitted? - fn ty_infer(&self, span: Span) -> Ty<'tcx>; + /// Returns the type to use when a type is omitted. + 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 @@ -86,12 +92,22 @@ fn projected_ty_from_poly_trait_ref(&self, fn record_ty(&self, hir_id: hir::HirId, ty: Ty<'tcx>, span: Span); } +pub enum SizedByDefault { + Yes, + No, +} + struct ConvertedBinding<'tcx> { item_name: ast::Ident, - ty: Ty<'tcx>, + kind: ConvertedBindingKind<'tcx>, span: Span, } +enum ConvertedBindingKind<'tcx> { + Equality(Ty<'tcx>), + Constraint(P<[hir::GenericBound]>), +} + #[derive(PartialEq)] enum GenericArgPosition { Type, @@ -145,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 @@ -180,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, ) }); @@ -192,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), .. @@ -223,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, @@ -248,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 @@ -269,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 { @@ -322,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); @@ -376,8 +391,10 @@ fn check_generic_arg_count( } err.emit(); - (provided > required, // `suppress_error` - potential_assoc_types) + ( + provided > required, // `suppress_error` + potential_assoc_types, + ) }; if reported_late_bound_region_err.is_none() @@ -391,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, @@ -401,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", @@ -444,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, @@ -498,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(); @@ -522,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(); } (_, _) => { @@ -543,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(); } @@ -556,15 +573,30 @@ pub fn create_substs_for_generic_args<'a, 'b>( } /// Given the type/lifetime/const arguments provided to some path (along with - /// an implicit `Self`, if this is a trait reference) returns the complete + /// an implicit `Self`, if this is a trait reference), returns the complete /// set of substitutions. This may involve applying defaulted type parameters. + /// Also returns back constriants on associated types. + /// + /// Example: + /// + /// ``` + /// T: std::ops::Index + /// ^1 ^^^^^^^^^^^^^^2 ^^^^3 ^^^^^^^^^^^4 + /// ``` + /// + /// 1. The `self_ty` here would refer to the type `T`. + /// 2. The path in question is the path to the trait `std::ops::Index`, + /// which will have been resolved to a `def_id` + /// 3. The `generic_args` contains info on the `<...>` contents. The `usize` type + /// parameters are returned in the `SubstsRef`, the associated type bindings like + /// `Output = u32` are returned in the `Vec` result. /// /// Note that the type listing given here is *exactly* what the user provided. - fn create_substs_for_ast_path(&self, + fn create_substs_for_ast_path<'a>(&self, span: Span, def_id: DefId, - generic_args: &hir::GenericArgs, - infer_types: bool, + generic_args: &'a hir::GenericArgs, + infer_args: bool, self_ty: Option>) -> (SubstsRef<'tcx>, Vec>, Option>) { @@ -589,7 +621,7 @@ fn create_substs_for_ast_path(&self, &generic_args, GenericArgPosition::Type, has_self, - infer_types, + infer_args, ); let is_object = self_ty.map_or(false, |ty| { @@ -616,7 +648,7 @@ fn create_substs_for_ast_path(&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) { @@ -633,11 +665,11 @@ fn create_substs_for_ast_path(&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 @@ -665,13 +697,14 @@ fn create_substs_for_ast_path(&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() @@ -679,20 +712,43 @@ fn create_substs_for_ast_path(&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() + } } } }, ); - let assoc_bindings = generic_args.bindings.iter().map(|binding| { - ConvertedBinding { - item_name: binding.ident, - ty: self.ast_ty_to_ty(&binding.ty), - span: binding.span, - } - }).collect(); + // Convert associated-type bindings or constraints into a separate vector. + // Example: Given this: + // + // T: Iterator + // + // The `T` is passed in as a self-type; the `Item = u32` is + // not a "type parameter" of the `Iterator` trait, but rather + // a restriction on `::Item`, so it is passed + // back separately. + let assoc_bindings = generic_args.bindings.iter() + .map(|binding| { + let kind = match binding.kind { + hir::TypeBindingKind::Equality { ref ty } => + ConvertedBindingKind::Equality(self.ast_ty_to_ty(ty)), + hir::TypeBindingKind::Constraint { ref bounds } => + ConvertedBindingKind::Constraint(bounds.clone()), + }; + ConvertedBinding { + item_name: binding.ident, + kind, + span: binding.span, + } + }) + .collect(); debug!("create_substs_for_ast_path(generic_params={:?}, self_ty={:?}) -> {:?}", generic_params, self_ty, substs); @@ -708,8 +764,8 @@ fn create_substs_for_ast_path(&self, /// are disallowed. Otherwise, they are pushed onto the vector given. pub fn instantiate_mono_trait_ref(&self, trait_ref: &hir::TraitRef, - self_ty: Ty<'tcx>) - -> ty::TraitRef<'tcx> + self_ty: Ty<'tcx> + ) -> ty::TraitRef<'tcx> { self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1); @@ -723,9 +779,9 @@ pub fn instantiate_mono_trait_ref(&self, pub(super) fn instantiate_poly_trait_ref_inner(&self, trait_ref: &hir::TraitRef, self_ty: Ty<'tcx>, - poly_projections: &mut Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>, - speculative: bool) - -> (ty::PolyTraitRef<'tcx>, Option>) + bounds: &mut Bounds<'tcx>, + speculative: bool, + ) -> (ty::PolyTraitRef<'tcx>, Option>) { let trait_def_id = trait_ref.trait_def_id(); @@ -742,36 +798,59 @@ pub(super) fn instantiate_poly_trait_ref_inner(&self, let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs)); let mut dup_bindings = FxHashMap::default(); - poly_projections.extend(assoc_bindings.iter().filter_map(|binding| { - // specify type to assert that error was already reported in Err case: - let predicate: Result<_, ErrorReported> = - self.ast_type_binding_to_poly_projection_predicate( - trait_ref.hir_ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings); - // okay to ignore Err because of ErrorReported (see above) - Some((predicate.ok()?, binding.span)) - })); - - debug!("instantiate_poly_trait_ref({:?}, projections={:?}) -> {:?}", - trait_ref, poly_projections, poly_trait_ref); + for binding in &assoc_bindings { + // Specify type to assert that error was already reported in `Err` case. + let _: Result<_, ErrorReported> = + self.add_predicates_for_ast_type_binding( + trait_ref.hir_ref_id, + poly_trait_ref, + binding, + bounds, + speculative, + &mut dup_bindings + ); + // Okay to ignore `Err` because of `ErrorReported` (see above). + } + + debug!("instantiate_poly_trait_ref({:?}, bounds={:?}) -> {:?}", + trait_ref, bounds, poly_trait_ref); (poly_trait_ref, potential_assoc_types) } + /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct + /// a full trait reference. The resulting trait reference is returned. This may also generate + /// auxiliary bounds, which are added to `bounds`. + /// + /// Example: + /// + /// ``` + /// poly_trait_ref = Iterator + /// self_ty = Foo + /// ``` + /// + /// this would return `Foo: Iterator` and add `::Item = u32` into `bounds`. + /// + /// **A note on binders:** against our usual convention, there is an implied bounder around + /// the `self_ty` and `poly_trait_ref` parameters here. So they may reference bound regions. + /// If for example you had `for<'a> Foo<'a>: Bar<'a>`, then the `self_ty` would be `Foo<'a>` + /// where `'a` is a bound region at depth 0. Similarly, the `poly_trait_ref` would be + /// `Bar<'a>`. The returned poly-trait-ref will have this binder instantiated explicitly, + /// however. pub fn instantiate_poly_trait_ref(&self, poly_trait_ref: &hir::PolyTraitRef, self_ty: Ty<'tcx>, - poly_projections: &mut Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>) - -> (ty::PolyTraitRef<'tcx>, Option>) + bounds: &mut Bounds<'tcx> + ) -> (ty::PolyTraitRef<'tcx>, Option>) { - self.instantiate_poly_trait_ref_inner(&poly_trait_ref.trait_ref, self_ty, - poly_projections, false) + self.instantiate_poly_trait_ref_inner(&poly_trait_ref.trait_ref, self_ty, bounds, false) } fn ast_path_to_mono_trait_ref(&self, - span: Span, - trait_def_id: DefId, - self_ty: Ty<'tcx>, - trait_segment: &hir::PathSegment) - -> ty::TraitRef<'tcx> + span: Span, + trait_def_id: DefId, + self_ty: Ty<'tcx>, + trait_segment: &hir::PathSegment + ) -> ty::TraitRef<'tcx> { let (substs, assoc_bindings, _) = self.create_substs_for_ast_trait_ref(span, @@ -812,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)) }) } @@ -828,15 +907,156 @@ fn trait_defines_associated_type_named(&self, }) } - fn ast_type_binding_to_poly_projection_predicate( + // Returns `true` if a bounds list includes `?Sized`. + pub fn is_unsized(&self, ast_bounds: &[hir::GenericBound], span: Span) -> bool { + let tcx = self.tcx(); + + // Try to find an unbound in bounds. + let mut unbound = None; + for ab in ast_bounds { + if let &hir::GenericBound::Trait(ref ptr, hir::TraitBoundModifier::Maybe) = ab { + if unbound.is_none() { + unbound = Some(ptr.trait_ref.clone()); + } else { + span_err!( + tcx.sess, + span, + E0203, + "type parameter has more than one relaxed default \ + bound, only one is supported" + ); + } + } + } + + let kind_id = tcx.lang_items().require(SizedTraitLangItem); + match unbound { + Some(ref tpb) => { + // FIXME(#8559) currently requires the unbound to be built-in. + if let Ok(kind_id) = kind_id { + if tpb.path.res != Res::Def(DefKind::Trait, kind_id) { + tcx.sess.span_warn( + span, + "default bound relaxed for a type parameter, but \ + this does nothing because the given bound is not \ + a default. Only `?Sized` is supported", + ); + } + } + } + _ if kind_id.is_ok() => { + return false; + } + // No lang item for `Sized`, so we can't add it as a bound. + None => {} + } + + true + } + + /// This helper takes a *converted* parameter type (`param_ty`) + /// and an *unconverted* list of bounds: + /// + /// ``` + /// fn foo + /// ^ ^^^^^ `ast_bounds` parameter, in HIR form + /// | + /// `param_ty`, in ty form + /// ``` + /// + /// It adds these `ast_bounds` into the `bounds` structure. + /// + /// **A note on binders:** there is an implied binder around + /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref` + /// for more details. + fn add_bounds(&self, + param_ty: Ty<'tcx>, + ast_bounds: &[hir::GenericBound], + bounds: &mut Bounds<'tcx>, + ) { + let mut trait_bounds = Vec::new(); + let mut region_bounds = Vec::new(); + + for ast_bound in ast_bounds { + match *ast_bound { + hir::GenericBound::Trait(ref b, hir::TraitBoundModifier::None) => + trait_bounds.push(b), + hir::GenericBound::Trait(_, hir::TraitBoundModifier::Maybe) => {} + hir::GenericBound::Outlives(ref l) => + region_bounds.push(l), + } + } + + for bound in trait_bounds { + let (poly_trait_ref, _) = self.instantiate_poly_trait_ref( + bound, + param_ty, + bounds, + ); + bounds.trait_bounds.push((poly_trait_ref, bound.span)) + } + + bounds.region_bounds.extend(region_bounds + .into_iter() + .map(|r| (self.ast_region_to_region(r, None), r.span)) + ); + } + + /// Translates a list of bounds from the HIR into the `Bounds` data structure. + /// The self-type for the bounds is given by `param_ty`. + /// + /// Example: + /// + /// ``` + /// fn foo() { } + /// ^ ^^^^^^^^^ ast_bounds + /// param_ty + /// ``` + /// + /// The `sized_by_default` parameter indicates if, in this context, the `param_ty` should be + /// considered `Sized` unless there is an explicit `?Sized` bound. This would be true in the + /// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`. + /// + /// `span` should be the declaration size of the parameter. + pub fn compute_bounds(&self, + param_ty: Ty<'tcx>, + ast_bounds: &[hir::GenericBound], + sized_by_default: SizedByDefault, + span: Span, + ) -> Bounds<'tcx> { + let mut bounds = Bounds::default(); + + self.add_bounds(param_ty, ast_bounds, &mut bounds); + bounds.trait_bounds.sort_by_key(|(t, _)| t.def_id()); + + bounds.implicitly_sized = if let SizedByDefault::Yes = sized_by_default { + if !self.is_unsized(ast_bounds, span) { + Some(span) + } else { + None + } + } else { + None + }; + + bounds + } + + /// Given an HIR binding like `Item = Foo` or `Item: Foo`, pushes the corresponding predicates + /// onto `bounds`. + /// + /// **A note on binders:** given something like `T: for<'a> Iterator`, the + /// `trait_ref` here will be `for<'a> T: Iterator`. The `binding` data however is from *inside* + /// the binder (e.g., `&'a u32`) and hence may reference bound regions. + fn add_predicates_for_ast_type_binding( &self, hir_ref_id: hir::HirId, trait_ref: ty::PolyTraitRef<'tcx>, binding: &ConvertedBinding<'tcx>, + bounds: &mut Bounds<'tcx>, speculative: bool, - dup_bindings: &mut FxHashMap) - -> Result, ErrorReported> - { + dup_bindings: &mut FxHashMap, + ) -> Result<(), ErrorReported> { let tcx = self.tcx(); if !speculative { @@ -851,40 +1071,43 @@ fn ast_type_binding_to_poly_projection_predicate( // trait SubTrait: SuperTrait { } // trait SuperTrait { type T; } // - // ... B : SubTrait ... + // ... B: SubTrait ... // ``` // // We want to produce `>::T == foo`. // Find any late-bound regions declared in `ty` that are not - // declared in the trait-ref. These are not wellformed. + // declared in the trait-ref. These are not well-formed. // // Example: // // for<'a> ::Item = &'a str // <-- 'a is bad // for<'a> >::Output = &'a str // <-- 'a is ok - let late_bound_in_trait_ref = tcx.collect_constrained_late_bound_regions(&trait_ref); - let late_bound_in_ty = - tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(binding.ty)); - debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref); - debug!("late_bound_in_ty = {:?}", late_bound_in_ty); - for br in late_bound_in_ty.difference(&late_bound_in_trait_ref) { - let br_name = match *br { - ty::BrNamed(_, name) => name, - _ => { - span_bug!( - binding.span, - "anonymous bound region {:?} in binding but not trait ref", - br); - } - }; - struct_span_err!(tcx.sess, + if let ConvertedBindingKind::Equality(ty) = binding.kind { + let late_bound_in_trait_ref = + tcx.collect_constrained_late_bound_regions(&trait_ref); + let late_bound_in_ty = + tcx.collect_referenced_late_bound_regions(&ty::Binder::bind(ty)); + debug!("late_bound_in_trait_ref = {:?}", late_bound_in_trait_ref); + debug!("late_bound_in_ty = {:?}", late_bound_in_ty); + for br in late_bound_in_ty.difference(&late_bound_in_trait_ref) { + let br_name = match *br { + ty::BrNamed(_, name) => name, + _ => { + span_bug!( binding.span, - E0582, - "binding for associated type `{}` references lifetime `{}`, \ - which does not appear in the trait input types", - binding.item_name, br_name) - .emit(); + "anonymous bound region {:?} in binding but not trait ref", + br); + } + }; + struct_span_err!(tcx.sess, + binding.span, + E0582, + "binding for associated type `{}` references lifetime `{}`, \ + which does not appear in the trait input types", + binding.item_name, br_name) + .emit(); + } } } @@ -929,16 +1152,39 @@ fn ast_type_binding_to_poly_projection_predicate( .or_insert(binding.span); } - Ok(candidate.map_bound(|trait_ref| { - ty::ProjectionPredicate { - projection_ty: ty::ProjectionTy::from_ref_and_name( - tcx, - trait_ref, - binding.item_name, - ), - ty: binding.ty, + match binding.kind { + ConvertedBindingKind::Equality(ref ty) => { + // "Desugar" a constraint like `T: Iterator` this to + // the "projection predicate" for: + // + // `::Item = u32` + bounds.projection_bounds.push((candidate.map_bound(|trait_ref| { + ty::ProjectionPredicate { + projection_ty: ty::ProjectionTy::from_ref_and_name( + tcx, + trait_ref, + binding.item_name, + ), + ty, + } + }), binding.span)); + } + ConvertedBindingKind::Constraint(ref ast_bounds) => { + // "Desugar" a constraint like `T: Iterator` to + // + // `::Item: Debug` + // + // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty` + // parameter to have a skipped binder. + let param_ty = tcx.mk_projection(assoc_ty.def_id, candidate.skip_binder().substs); + self.add_bounds( + param_ty, + ast_bounds, + bounds, + ); } - })) + } + Ok(()) } fn ast_path_to_ty(&self, @@ -972,7 +1218,7 @@ fn conv_object_ty_poly_trait_ref(&self, { let tcx = self.tcx(); - let mut projection_bounds = Vec::new(); + let mut bounds = Bounds::default(); let mut potential_assoc_types = Vec::new(); let dummy_self = self.tcx().types.trait_object_dummy_self; // FIXME: we want to avoid collecting into a `Vec` here, but simply cloning the iterator is @@ -984,7 +1230,7 @@ fn conv_object_ty_poly_trait_ref(&self, let (trait_ref, cur_potential_assoc_types) = self.instantiate_poly_trait_ref( trait_bound, dummy_self, - &mut projection_bounds + &mut bounds, ); potential_assoc_types.extend(cur_potential_assoc_types.into_iter().flatten()); (trait_ref, trait_bound.span) @@ -1072,14 +1318,14 @@ fn conv_object_ty_poly_trait_ref(&self, // which is uglier but works. See the discussion in #56288 for alternatives. if !references_self { // Include projections defined on supertraits. - projection_bounds.push((pred, DUMMY_SP)) + bounds.projection_bounds.push((pred, DUMMY_SP)) } } _ => () } } - for (projection_bound, _) in &projection_bounds { + for (projection_bound, _) in &bounds.projection_bounds { associated_types.remove(&projection_bound.projection_def_id()); } @@ -1159,7 +1405,7 @@ fn conv_object_ty_poly_trait_ref(&self, let existential_trait_refs = regular_traits.iter().map(|i| { i.trait_ref().map_bound(|trait_ref| self.trait_ref_to_existential(trait_ref)) }); - let existential_projections = projection_bounds.iter().map(|(bound, _)| { + let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| { bound.map_bound(|b| { let trait_ref = self.trait_ref_to_existential(b.projection_ty.trait_ref(tcx)); ty::ExistentialProjection { @@ -1193,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"); @@ -1564,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(); @@ -1716,7 +1962,7 @@ pub fn res_to_ty(&self, let span = path.span; match path.res { Res::Def(DefKind::Existential, did) => { - // Check for desugared impl trait. + // Check for desugared `impl Trait`. assert!(ty::is_impl_trait_defn(tcx, did).is_none()); let item_segment = path.segments.split_last().unwrap(); self.prohibit_generics(item_segment.1); @@ -1767,18 +2013,18 @@ pub fn res_to_ty(&self, &tcx.hir().local_def_id_from_hir_id(hir_id)]; tcx.mk_ty_param(index, tcx.hir().name_by_hir_id(hir_id).as_interned_str()) } - Res::SelfTy(_, Some(def_id)) => { - // `Self` in impl (we know the concrete type). + Res::SelfTy(Some(_), None) => { + // `Self` in trait or type alias. assert_eq!(opt_self_ty, None); self.prohibit_generics(&path.segments); - // Try to evaluate any array length constants - self.normalize_ty(span, tcx.at(span).type_of(def_id)) + tcx.mk_self_type() } - Res::SelfTy(Some(_), None) => { - // `Self` in trait. + Res::SelfTy(_, Some(def_id)) => { + // `Self` in impl (we know the concrete type). assert_eq!(opt_self_ty, None); self.prohibit_generics(&path.segments); - tcx.mk_self_type() + // Try to evaluate any array length constants. + self.normalize_ty(span, tcx.at(span).type_of(def_id)) } Res::Def(DefKind::AssocTy, def_id) => { debug_assert!(path.segments.len() >= 2); @@ -1829,7 +2075,7 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> { } hir::TyKind::Rptr(ref region, ref mt) => { let r = self.ast_region_to_region(region, None); - debug!("Ref r={:?}", r); + debug!("ast_ty_to_ty: r={:?}", r); let t = self.ast_ty_to_ty(&mt.ty); tcx.mk_ref(r, ty::TypeAndMut {ty: t, mutbl: mt.mutbl}) } @@ -1856,7 +2102,7 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> { hir::TyKind::Def(item_id, ref lifetimes) => { let did = tcx.hir().local_def_id_from_hir_id(item_id.id); self.impl_trait_ty_to_ty(did, lifetimes) - }, + } hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => { debug!("ast_ty_to_ty: qself={:?} segment={:?}", qself, segment); let ty = self.ast_ty_to_ty(qself); @@ -1887,10 +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) - } - hir::TyKind::Err => { - tcx.types.err + self.ty_infer(None, ast_ty.span) } hir::TyKind::CVarArgs(lt) => { let va_list_did = match tcx.lang_items().va_list() { @@ -1901,12 +2144,28 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> { let region = self.ast_region_to_region(<, None); tcx.type_of(va_list_did).subst(tcx, &[region.into()]) } + hir::TyKind::Err => { + tcx.types.err + } }; + debug!("ast_ty_to_ty: result_ty={:?}", result_ty); + self.record_ty(ast_ty.hir_id, result_ty, ast_ty.span); 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, @@ -1937,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_) } @@ -1979,7 +2236,7 @@ pub fn impl_trait_ty_to_ty( _ => bug!() } } else { - // Replace all parent lifetimes with 'static. + // Replace all parent lifetimes with `'static`. match param.kind { GenericParamDefKind::Lifetime => { tcx.lifetimes.re_static.into() @@ -1988,7 +2245,7 @@ pub fn impl_trait_ty_to_ty( } } }); - debug!("impl_trait_ty_to_ty: final substs = {:?}", substs); + debug!("impl_trait_ty_to_ty: substs={:?}", substs); let ty = tcx.mk_opaque(def_id, substs); debug!("impl_trait_ty_to_ty: {}", ty); @@ -2117,20 +2374,57 @@ fn compute_object_lifetime_bound(&self, } } -// A helper struct for conveniently grouping a set of bounds which we pass to -// and return from functions in multiple places. -#[derive(PartialEq, Eq, Clone, Debug)] +/// Collects together a list of bounds that are applied to some type, +/// after they've been converted into `ty` form (from the HIR +/// representations). These lists of bounds occur in many places in +/// Rust's syntax: +/// +/// ``` +/// trait Foo: Bar + Baz { } +/// ^^^^^^^^^ supertrait list bounding the `Self` type parameter +/// +/// fn foo() { } +/// ^^^^^^^^^ bounding the type parameter `T` +/// +/// impl dyn Bar + Baz +/// ^^^^^^^^^ bounding the forgotten dynamic type +/// ``` +/// +/// Our representation is a bit mixed here -- in some cases, we +/// include the self type (e.g., `trait_bounds`) but in others we do +#[derive(Default, PartialEq, Eq, Clone, Debug)] pub struct Bounds<'tcx> { + /// A list of region bounds on the (implicit) self type. So if you + /// had `T: 'a + 'b` this might would be a list `['a, 'b]` (but + /// the `T` is not explicitly included). pub region_bounds: Vec<(ty::Region<'tcx>, Span)>, - pub implicitly_sized: Option, + + /// A list of trait bounds. So if you had `T: Debug` this would be + /// `T: Debug`. Note that the self-type is explicit here. pub trait_bounds: Vec<(ty::PolyTraitRef<'tcx>, Span)>, + + /// A list of projection equality bounds. So if you had `T: + /// Iterator` this would include `::Item => u32`. Note that the self-type is explicit + /// here. pub projection_bounds: Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>, + + /// `Some` if there is *no* `?Sized` predicate. The `span` + /// is the location in the source of the `T` declaration which can + /// be cited as the source of the `T: Sized` requirement. + pub implicitly_sized: Option, } -impl<'a, 'gcx, 'tcx> Bounds<'tcx> { - pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, param_ty: Ty<'tcx>) - -> Vec<(ty::Predicate<'tcx>, Span)> - { +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<'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| {