1 use rustc_data_structures::fx::FxHashMap; 2 use rustc_errors::struct_span_err; 3 use rustc_hir as hir; 4 use rustc_hir::def::{DefKind, Res}; 5 use rustc_hir::def_id::{DefId, LocalDefId}; 6 use rustc_lint_defs::Applicability; 7 use rustc_middle::ty::{self as ty, Ty, TypeVisitableExt}; 8 use rustc_span::symbol::Ident; 9 use rustc_span::{ErrorGuaranteed, Span}; 10 use rustc_trait_selection::traits; 11 12 use crate::astconv::{ 13 AstConv, ConvertedBinding, ConvertedBindingKind, OnlySelfBounds, PredicateFilter, 14 }; 15 use crate::bounds::Bounds; 16 use crate::errors::{MultipleRelaxedDefaultBounds, ValueOfAssociatedStructAlreadySpecified}; 17 18 impl<'tcx> dyn AstConv<'tcx> + '_ { 19 /// Sets `implicitly_sized` to true on `Bounds` if necessary add_implicitly_sized( &self, bounds: &mut Bounds<'tcx>, self_ty: Ty<'tcx>, ast_bounds: &'tcx [hir::GenericBound<'tcx>], self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, span: Span, )20 pub(crate) fn add_implicitly_sized( 21 &self, 22 bounds: &mut Bounds<'tcx>, 23 self_ty: Ty<'tcx>, 24 ast_bounds: &'tcx [hir::GenericBound<'tcx>], 25 self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, 26 span: Span, 27 ) { 28 let tcx = self.tcx(); 29 30 // Try to find an unbound in bounds. 31 let mut unbound = None; 32 let mut search_bounds = |ast_bounds: &'tcx [hir::GenericBound<'tcx>]| { 33 for ab in ast_bounds { 34 if let hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::Maybe) = ab { 35 if unbound.is_none() { 36 unbound = Some(&ptr.trait_ref); 37 } else { 38 tcx.sess.emit_err(MultipleRelaxedDefaultBounds { span }); 39 } 40 } 41 } 42 }; 43 search_bounds(ast_bounds); 44 if let Some((self_ty, where_clause)) = self_ty_where_predicates { 45 for clause in where_clause { 46 if let hir::WherePredicate::BoundPredicate(pred) = clause { 47 if pred.is_param_bound(self_ty.to_def_id()) { 48 search_bounds(pred.bounds); 49 } 50 } 51 } 52 } 53 54 let sized_def_id = tcx.lang_items().sized_trait(); 55 match (&sized_def_id, unbound) { 56 (Some(sized_def_id), Some(tpb)) 57 if tpb.path.res == Res::Def(DefKind::Trait, *sized_def_id) => 58 { 59 // There was in fact a `?Sized` bound, return without doing anything 60 return; 61 } 62 (_, Some(_)) => { 63 // There was a `?Trait` bound, but it was not `?Sized`; warn. 64 tcx.sess.span_warn( 65 span, 66 "default bound relaxed for a type parameter, but \ 67 this does nothing because the given bound is not \ 68 a default; only `?Sized` is supported", 69 ); 70 // Otherwise, add implicitly sized if `Sized` is available. 71 } 72 _ => { 73 // There was no `?Sized` bound; add implicitly sized if `Sized` is available. 74 } 75 } 76 if sized_def_id.is_none() { 77 // No lang item for `Sized`, so we can't add it as a bound. 78 return; 79 } 80 bounds.push_sized(tcx, self_ty, span); 81 } 82 83 /// This helper takes a *converted* parameter type (`param_ty`) 84 /// and an *unconverted* list of bounds: 85 /// 86 /// ```text 87 /// fn foo<T: Debug> 88 /// ^ ^^^^^ `ast_bounds` parameter, in HIR form 89 /// | 90 /// `param_ty`, in ty form 91 /// ``` 92 /// 93 /// It adds these `ast_bounds` into the `bounds` structure. 94 /// 95 /// **A note on binders:** there is an implied binder around 96 /// `param_ty` and `ast_bounds`. See `instantiate_poly_trait_ref` 97 /// for more details. 98 #[instrument(level = "debug", skip(self, ast_bounds, bounds))] add_bounds<'hir, I: Iterator<Item = &'hir hir::GenericBound<'hir>>>( &self, param_ty: Ty<'tcx>, ast_bounds: I, bounds: &mut Bounds<'tcx>, bound_vars: &'tcx ty::List<ty::BoundVariableKind>, only_self_bounds: OnlySelfBounds, )99 pub(crate) fn add_bounds<'hir, I: Iterator<Item = &'hir hir::GenericBound<'hir>>>( 100 &self, 101 param_ty: Ty<'tcx>, 102 ast_bounds: I, 103 bounds: &mut Bounds<'tcx>, 104 bound_vars: &'tcx ty::List<ty::BoundVariableKind>, 105 only_self_bounds: OnlySelfBounds, 106 ) { 107 for ast_bound in ast_bounds { 108 match ast_bound { 109 hir::GenericBound::Trait(poly_trait_ref, modifier) => { 110 let (constness, polarity) = match modifier { 111 hir::TraitBoundModifier::MaybeConst => { 112 (ty::BoundConstness::ConstIfConst, ty::ImplPolarity::Positive) 113 } 114 hir::TraitBoundModifier::None => { 115 (ty::BoundConstness::NotConst, ty::ImplPolarity::Positive) 116 } 117 hir::TraitBoundModifier::Negative => { 118 (ty::BoundConstness::NotConst, ty::ImplPolarity::Negative) 119 } 120 hir::TraitBoundModifier::Maybe => continue, 121 }; 122 let _ = self.instantiate_poly_trait_ref( 123 &poly_trait_ref.trait_ref, 124 poly_trait_ref.span, 125 constness, 126 polarity, 127 param_ty, 128 bounds, 129 false, 130 only_self_bounds, 131 ); 132 } 133 &hir::GenericBound::LangItemTrait(lang_item, span, hir_id, args) => { 134 self.instantiate_lang_item_trait_ref( 135 lang_item, 136 span, 137 hir_id, 138 args, 139 param_ty, 140 bounds, 141 only_self_bounds, 142 ); 143 } 144 hir::GenericBound::Outlives(lifetime) => { 145 let region = self.ast_region_to_region(lifetime, None); 146 bounds.push_region_bound( 147 self.tcx(), 148 ty::Binder::bind_with_vars( 149 ty::OutlivesPredicate(param_ty, region), 150 bound_vars, 151 ), 152 lifetime.ident.span, 153 ); 154 } 155 } 156 } 157 } 158 159 /// Translates a list of bounds from the HIR into the `Bounds` data structure. 160 /// The self-type for the bounds is given by `param_ty`. 161 /// 162 /// Example: 163 /// 164 /// ```ignore (illustrative) 165 /// fn foo<T: Bar + Baz>() { } 166 /// // ^ ^^^^^^^^^ ast_bounds 167 /// // param_ty 168 /// ``` 169 /// 170 /// The `sized_by_default` parameter indicates if, in this context, the `param_ty` should be 171 /// considered `Sized` unless there is an explicit `?Sized` bound. This would be true in the 172 /// example above, but is not true in supertrait listings like `trait Foo: Bar + Baz`. 173 /// 174 /// `span` should be the declaration size of the parameter. compute_bounds( &self, param_ty: Ty<'tcx>, ast_bounds: &[hir::GenericBound<'_>], filter: PredicateFilter, ) -> Bounds<'tcx>175 pub(crate) fn compute_bounds( 176 &self, 177 param_ty: Ty<'tcx>, 178 ast_bounds: &[hir::GenericBound<'_>], 179 filter: PredicateFilter, 180 ) -> Bounds<'tcx> { 181 let mut bounds = Bounds::default(); 182 183 let only_self_bounds = match filter { 184 PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => { 185 OnlySelfBounds(false) 186 } 187 PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => OnlySelfBounds(true), 188 }; 189 190 self.add_bounds( 191 param_ty, 192 ast_bounds.iter().filter(|bound| { 193 match filter { 194 PredicateFilter::All 195 | PredicateFilter::SelfOnly 196 | PredicateFilter::SelfAndAssociatedTypeBounds => true, 197 PredicateFilter::SelfThatDefines(assoc_name) => { 198 if let Some(trait_ref) = bound.trait_ref() 199 && let Some(trait_did) = trait_ref.trait_def_id() 200 && self.tcx().trait_may_define_assoc_item(trait_did, assoc_name) 201 { 202 true 203 } else { 204 false 205 } 206 } 207 } 208 }), 209 &mut bounds, 210 ty::List::empty(), 211 only_self_bounds, 212 ); 213 debug!(?bounds); 214 215 bounds 216 } 217 218 /// Given an HIR binding like `Item = Foo` or `Item: Foo`, pushes the corresponding predicates 219 /// onto `bounds`. 220 /// 221 /// **A note on binders:** given something like `T: for<'a> Iterator<Item = &'a u32>`, the 222 /// `trait_ref` here will be `for<'a> T: Iterator`. The `binding` data however is from *inside* 223 /// the binder (e.g., `&'a u32`) and hence may reference bound regions. 224 #[instrument(level = "debug", skip(self, bounds, speculative, dup_bindings, path_span))] 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<DefId, Span>, path_span: Span, constness: ty::BoundConstness, only_self_bounds: OnlySelfBounds, polarity: ty::ImplPolarity, ) -> Result<(), ErrorGuaranteed>225 pub(super) fn add_predicates_for_ast_type_binding( 226 &self, 227 hir_ref_id: hir::HirId, 228 trait_ref: ty::PolyTraitRef<'tcx>, 229 binding: &ConvertedBinding<'_, 'tcx>, 230 bounds: &mut Bounds<'tcx>, 231 speculative: bool, 232 dup_bindings: &mut FxHashMap<DefId, Span>, 233 path_span: Span, 234 constness: ty::BoundConstness, 235 only_self_bounds: OnlySelfBounds, 236 polarity: ty::ImplPolarity, 237 ) -> Result<(), ErrorGuaranteed> { 238 // Given something like `U: SomeTrait<T = X>`, we want to produce a 239 // predicate like `<U as SomeTrait>::T = X`. This is somewhat 240 // subtle in the event that `T` is defined in a supertrait of 241 // `SomeTrait`, because in that case we need to upcast. 242 // 243 // That is, consider this case: 244 // 245 // ``` 246 // trait SubTrait: SuperTrait<i32> { } 247 // trait SuperTrait<A> { type T; } 248 // 249 // ... B: SubTrait<T = foo> ... 250 // ``` 251 // 252 // We want to produce `<B as SuperTrait<i32>>::T == foo`. 253 254 let tcx = self.tcx(); 255 256 let return_type_notation = 257 binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation; 258 259 let candidate = if return_type_notation { 260 if self.trait_defines_associated_item_named( 261 trait_ref.def_id(), 262 ty::AssocKind::Fn, 263 binding.item_name, 264 ) { 265 trait_ref 266 } else { 267 self.one_bound_for_assoc_method( 268 traits::supertraits(tcx, trait_ref), 269 trait_ref.print_only_trait_path(), 270 binding.item_name, 271 path_span, 272 )? 273 } 274 } else if self.trait_defines_associated_item_named( 275 trait_ref.def_id(), 276 ty::AssocKind::Type, 277 binding.item_name, 278 ) { 279 // Simple case: X is defined in the current trait. 280 trait_ref 281 } else { 282 // Otherwise, we have to walk through the supertraits to find 283 // those that do. 284 self.one_bound_for_assoc_type( 285 || traits::supertraits(tcx, trait_ref), 286 trait_ref.skip_binder().print_only_trait_name(), 287 binding.item_name, 288 path_span, 289 match binding.kind { 290 ConvertedBindingKind::Equality(term) => Some(term), 291 _ => None, 292 }, 293 )? 294 }; 295 296 let (assoc_ident, def_scope) = 297 tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id); 298 299 // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead 300 // of calling `filter_by_name_and_kind`. 301 let find_item_of_kind = |kind| { 302 tcx.associated_items(candidate.def_id()) 303 .filter_by_name_unhygienic(assoc_ident.name) 304 .find(|i| i.kind == kind && i.ident(tcx).normalize_to_macros_2_0() == assoc_ident) 305 }; 306 let assoc_item = if return_type_notation { 307 find_item_of_kind(ty::AssocKind::Fn) 308 } else { 309 find_item_of_kind(ty::AssocKind::Type) 310 .or_else(|| find_item_of_kind(ty::AssocKind::Const)) 311 } 312 .expect("missing associated type"); 313 314 if !assoc_item.visibility(tcx).is_accessible_from(def_scope, tcx) { 315 tcx.sess 316 .struct_span_err( 317 binding.span, 318 format!("{} `{}` is private", assoc_item.kind, binding.item_name), 319 ) 320 .span_label(binding.span, format!("private {}", assoc_item.kind)) 321 .emit(); 322 } 323 tcx.check_stability(assoc_item.def_id, Some(hir_ref_id), binding.span, None); 324 325 if !speculative { 326 dup_bindings 327 .entry(assoc_item.def_id) 328 .and_modify(|prev_span| { 329 tcx.sess.emit_err(ValueOfAssociatedStructAlreadySpecified { 330 span: binding.span, 331 prev_span: *prev_span, 332 item_name: binding.item_name, 333 def_path: tcx.def_path_str(assoc_item.container_id(tcx)), 334 }); 335 }) 336 .or_insert(binding.span); 337 } 338 339 let projection_ty = if return_type_notation { 340 let mut emitted_bad_param_err = false; 341 // If we have an method return type bound, then we need to substitute 342 // the method's early bound params with suitable late-bound params. 343 let mut num_bound_vars = candidate.bound_vars().len(); 344 let substs = 345 candidate.skip_binder().substs.extend_to(tcx, assoc_item.def_id, |param, _| { 346 let subst = match param.kind { 347 ty::GenericParamDefKind::Lifetime => ty::Region::new_late_bound( 348 tcx, 349 ty::INNERMOST, 350 ty::BoundRegion { 351 var: ty::BoundVar::from_usize(num_bound_vars), 352 kind: ty::BoundRegionKind::BrNamed(param.def_id, param.name), 353 }, 354 ) 355 .into(), 356 ty::GenericParamDefKind::Type { .. } => { 357 if !emitted_bad_param_err { 358 tcx.sess.emit_err( 359 crate::errors::ReturnTypeNotationIllegalParam::Type { 360 span: path_span, 361 param_span: tcx.def_span(param.def_id), 362 }, 363 ); 364 emitted_bad_param_err = true; 365 } 366 Ty::new_bound( 367 tcx, 368 ty::INNERMOST, 369 ty::BoundTy { 370 var: ty::BoundVar::from_usize(num_bound_vars), 371 kind: ty::BoundTyKind::Param(param.def_id, param.name), 372 }, 373 ) 374 .into() 375 } 376 ty::GenericParamDefKind::Const { .. } => { 377 if !emitted_bad_param_err { 378 tcx.sess.emit_err( 379 crate::errors::ReturnTypeNotationIllegalParam::Const { 380 span: path_span, 381 param_span: tcx.def_span(param.def_id), 382 }, 383 ); 384 emitted_bad_param_err = true; 385 } 386 let ty = tcx 387 .type_of(param.def_id) 388 .no_bound_vars() 389 .expect("ct params cannot have early bound vars"); 390 ty::Const::new_bound( 391 tcx, 392 ty::INNERMOST, 393 ty::BoundVar::from_usize(num_bound_vars), 394 ty, 395 ) 396 .into() 397 } 398 }; 399 num_bound_vars += 1; 400 subst 401 }); 402 403 // Next, we need to check that the return-type notation is being used on 404 // an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait). 405 let output = tcx.fn_sig(assoc_item.def_id).skip_binder().output(); 406 let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind() 407 && tcx.is_impl_trait_in_trait(alias_ty.def_id) 408 { 409 alias_ty 410 } else { 411 return Err(self.tcx().sess.emit_err( 412 crate::errors::ReturnTypeNotationOnNonRpitit { 413 span: binding.span, 414 ty: tcx.liberate_late_bound_regions(assoc_item.def_id, output), 415 fn_span: tcx.hir().span_if_local(assoc_item.def_id), 416 note: (), 417 }, 418 )); 419 }; 420 421 // Finally, move the fn return type's bound vars over to account for the early bound 422 // params (and trait ref's late bound params). This logic is very similar to 423 // `Predicate::subst_supertrait`, and it's no coincidence why. 424 let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output); 425 let subst_output = ty::EarlyBinder::bind(shifted_output).subst(tcx, substs); 426 427 let bound_vars = tcx.late_bound_vars(binding.hir_id); 428 ty::Binder::bind_with_vars(subst_output, bound_vars) 429 } else { 430 // Include substitutions for generic parameters of associated types 431 candidate.map_bound(|trait_ref| { 432 let ident = Ident::new(assoc_item.name, binding.item_name.span); 433 let item_segment = hir::PathSegment { 434 ident, 435 hir_id: binding.hir_id, 436 res: Res::Err, 437 args: Some(binding.gen_args), 438 infer_args: false, 439 }; 440 441 let substs_trait_ref_and_assoc_item = self.create_substs_for_associated_item( 442 path_span, 443 assoc_item.def_id, 444 &item_segment, 445 trait_ref.substs, 446 ); 447 448 debug!(?substs_trait_ref_and_assoc_item); 449 450 tcx.mk_alias_ty(assoc_item.def_id, substs_trait_ref_and_assoc_item) 451 }) 452 }; 453 454 if !speculative { 455 // Find any late-bound regions declared in `ty` that are not 456 // declared in the trait-ref or assoc_item. These are not well-formed. 457 // 458 // Example: 459 // 460 // for<'a> <T as Iterator>::Item = &'a str // <-- 'a is bad 461 // for<'a> <T as FnMut<(&'a u32,)>>::Output = &'a str // <-- 'a is ok 462 if let ConvertedBindingKind::Equality(ty) = binding.kind { 463 let late_bound_in_trait_ref = 464 tcx.collect_constrained_late_bound_regions(&projection_ty); 465 let late_bound_in_ty = 466 tcx.collect_referenced_late_bound_regions(&trait_ref.rebind(ty)); 467 debug!(?late_bound_in_trait_ref); 468 debug!(?late_bound_in_ty); 469 470 // FIXME: point at the type params that don't have appropriate lifetimes: 471 // struct S1<F: for<'a> Fn(&i32, &i32) -> &'a i32>(F); 472 // ---- ---- ^^^^^^^ 473 self.validate_late_bound_regions( 474 late_bound_in_trait_ref, 475 late_bound_in_ty, 476 |br_name| { 477 struct_span_err!( 478 tcx.sess, 479 binding.span, 480 E0582, 481 "binding for associated type `{}` references {}, \ 482 which does not appear in the trait input types", 483 binding.item_name, 484 br_name 485 ) 486 }, 487 ); 488 } 489 } 490 491 match binding.kind { 492 ConvertedBindingKind::Equality(..) if return_type_notation => { 493 return Err(self.tcx().sess.emit_err( 494 crate::errors::ReturnTypeNotationEqualityBound { span: binding.span }, 495 )); 496 } 497 ConvertedBindingKind::Equality(mut term) => { 498 // "Desugar" a constraint like `T: Iterator<Item = u32>` this to 499 // the "projection predicate" for: 500 // 501 // `<T as Iterator>::Item = u32` 502 let assoc_item_def_id = projection_ty.skip_binder().def_id; 503 let def_kind = tcx.def_kind(assoc_item_def_id); 504 match (def_kind, term.unpack()) { 505 (hir::def::DefKind::AssocTy, ty::TermKind::Ty(_)) 506 | (hir::def::DefKind::AssocConst, ty::TermKind::Const(_)) => (), 507 (_, _) => { 508 let got = if let Some(_) = term.ty() { "type" } else { "constant" }; 509 let expected = tcx.def_descr(assoc_item_def_id); 510 let mut err = tcx.sess.struct_span_err( 511 binding.span, 512 format!("expected {expected} bound, found {got}"), 513 ); 514 err.span_note( 515 tcx.def_span(assoc_item_def_id), 516 format!("{expected} defined here"), 517 ); 518 519 if let hir::def::DefKind::AssocConst = def_kind 520 && let Some(t) = term.ty() && (t.is_enum() || t.references_error()) 521 && tcx.features().associated_const_equality { 522 err.span_suggestion( 523 binding.span, 524 "if equating a const, try wrapping with braces", 525 format!("{} = {{ const }}", binding.item_name), 526 Applicability::HasPlaceholders, 527 ); 528 } 529 let reported = err.emit(); 530 term = match def_kind { 531 hir::def::DefKind::AssocTy => Ty::new_error(tcx, reported).into(), 532 hir::def::DefKind::AssocConst => ty::Const::new_error( 533 tcx, 534 reported, 535 tcx.type_of(assoc_item_def_id) 536 .subst(tcx, projection_ty.skip_binder().substs), 537 ) 538 .into(), 539 _ => unreachable!(), 540 }; 541 } 542 } 543 bounds.push_projection_bound( 544 tcx, 545 projection_ty 546 .map_bound(|projection_ty| ty::ProjectionPredicate { projection_ty, term }), 547 binding.span, 548 ); 549 } 550 ConvertedBindingKind::Constraint(ast_bounds) => { 551 // "Desugar" a constraint like `T: Iterator<Item: Debug>` to 552 // 553 // `<T as Iterator>::Item: Debug` 554 // 555 // Calling `skip_binder` is okay, because `add_bounds` expects the `param_ty` 556 // parameter to have a skipped binder. 557 // 558 // NOTE: If `only_self_bounds` is true, do NOT expand this associated 559 // type bound into a trait predicate, since we only want to add predicates 560 // for the `Self` type. 561 if !only_self_bounds.0 { 562 let param_ty = Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder()); 563 self.add_bounds( 564 param_ty, 565 ast_bounds.iter(), 566 bounds, 567 projection_ty.bound_vars(), 568 only_self_bounds, 569 ); 570 } 571 } 572 } 573 Ok(()) 574 } 575 } 576