@@ -4,6 +4,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError;
4
4
use crate :: infer:: lexical_region_resolve:: RegionResolutionError ;
5
5
use crate :: infer:: { SubregionOrigin , TypeTrace } ;
6
6
use crate :: traits:: { ObligationCauseCode , UnifyReceiverContext } ;
7
+ use rustc_data_structures:: stable_set:: FxHashSet ;
7
8
use rustc_errors:: { struct_span_err, Applicability , DiagnosticBuilder , ErrorReported } ;
8
9
use rustc_hir:: def_id:: DefId ;
9
10
use rustc_hir:: intravisit:: { walk_ty, ErasedMap , NestedVisitorMap , Visitor } ;
@@ -185,17 +186,20 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
185
186
}
186
187
}
187
188
if let SubregionOrigin :: Subtype ( box TypeTrace { cause, .. } ) = & sub_origin {
188
- if let ObligationCauseCode :: ItemObligation ( item_def_id) = cause. code {
189
+ let code = match & cause. code {
190
+ ObligationCauseCode :: MatchImpl ( parent, ..) => & * * parent,
191
+ _ => & cause. code ,
192
+ } ;
193
+ if let ObligationCauseCode :: ItemObligation ( item_def_id) = * code {
189
194
// Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static`
190
195
// lifetime as above, but called using a fully-qualified path to the method:
191
196
// `Foo::qux(bar)`.
192
- let mut v = TraitObjectVisitor ( vec ! [ ] ) ;
197
+ let mut v = TraitObjectVisitor ( FxHashSet :: default ( ) ) ;
193
198
v. visit_ty ( param. param_ty ) ;
194
199
if let Some ( ( ident, self_ty) ) =
195
- self . get_impl_ident_and_self_ty_from_trait ( item_def_id, & v. 0 [ .. ] )
200
+ self . get_impl_ident_and_self_ty_from_trait ( item_def_id, & v. 0 )
196
201
{
197
- if self . suggest_constrain_dyn_trait_in_impl ( & mut err, & v. 0 [ ..] , ident, self_ty)
198
- {
202
+ if self . suggest_constrain_dyn_trait_in_impl ( & mut err, & v. 0 , ident, self_ty) {
199
203
override_error_code = Some ( ident) ;
200
204
}
201
205
}
@@ -336,7 +340,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
336
340
fn get_impl_ident_and_self_ty_from_trait (
337
341
& self ,
338
342
def_id : DefId ,
339
- trait_objects : & [ DefId ] ,
343
+ trait_objects : & FxHashSet < DefId > ,
340
344
) -> Option < ( Ident , & ' tcx hir:: Ty < ' tcx > ) > {
341
345
let tcx = self . tcx ( ) ;
342
346
match tcx. hir ( ) . get_if_local ( def_id) {
@@ -373,9 +377,10 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
373
377
// multiple `impl`s for the same trait like
374
378
// `impl Foo for Box<dyn Bar>` and `impl Foo for dyn Bar`.
375
379
// In that case, only the first one will get suggestions.
376
- let mut hir_v = HirTraitObjectVisitor ( vec ! [ ] , * did) ;
380
+ let mut traits = vec ! [ ] ;
381
+ let mut hir_v = HirTraitObjectVisitor ( & mut traits, * did) ;
377
382
hir_v. visit_ty ( self_ty) ;
378
- !hir_v . 0 . is_empty ( )
383
+ !traits . is_empty ( )
379
384
} ) =>
380
385
{
381
386
Some ( self_ty)
@@ -417,33 +422,34 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
417
422
_ => return false ,
418
423
} ;
419
424
420
- let mut v = TraitObjectVisitor ( vec ! [ ] ) ;
425
+ let mut v = TraitObjectVisitor ( FxHashSet :: default ( ) ) ;
421
426
v. visit_ty ( ty) ;
422
427
423
428
// Get the `Ident` of the method being called and the corresponding `impl` (to point at
424
429
// `Bar` in `impl Foo for dyn Bar {}` and the definition of the method being called).
425
430
let ( ident, self_ty) =
426
- match self . get_impl_ident_and_self_ty_from_trait ( instance. def_id ( ) , & v. 0 [ .. ] ) {
431
+ match self . get_impl_ident_and_self_ty_from_trait ( instance. def_id ( ) , & v. 0 ) {
427
432
Some ( ( ident, self_ty) ) => ( ident, self_ty) ,
428
433
None => return false ,
429
434
} ;
430
435
431
436
// Find the trait object types in the argument, so we point at *only* the trait object.
432
- self . suggest_constrain_dyn_trait_in_impl ( err, & v. 0 [ .. ] , ident, self_ty)
437
+ self . suggest_constrain_dyn_trait_in_impl ( err, & v. 0 , ident, self_ty)
433
438
}
434
439
435
440
fn suggest_constrain_dyn_trait_in_impl (
436
441
& self ,
437
442
err : & mut DiagnosticBuilder < ' _ > ,
438
- found_dids : & [ DefId ] ,
443
+ found_dids : & FxHashSet < DefId > ,
439
444
ident : Ident ,
440
445
self_ty : & hir:: Ty < ' _ > ,
441
446
) -> bool {
442
447
let mut suggested = false ;
443
448
for found_did in found_dids {
444
- let mut hir_v = HirTraitObjectVisitor ( vec ! [ ] , * found_did) ;
449
+ let mut traits = vec ! [ ] ;
450
+ let mut hir_v = HirTraitObjectVisitor ( & mut traits, * found_did) ;
445
451
hir_v. visit_ty ( & self_ty) ;
446
- for span in & hir_v . 0 {
452
+ for span in & traits {
447
453
let mut multi_span: MultiSpan = vec ! [ * span] . into ( ) ;
448
454
multi_span. push_span_label (
449
455
* span,
@@ -468,14 +474,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
468
474
}
469
475
470
476
/// Collect all the trait objects in a type that could have received an implicit `'static` lifetime.
471
- struct TraitObjectVisitor ( Vec < DefId > ) ;
477
+ pub ( super ) struct TraitObjectVisitor ( pub ( super ) FxHashSet < DefId > ) ;
472
478
473
479
impl TypeVisitor < ' _ > for TraitObjectVisitor {
474
480
fn visit_ty ( & mut self , t : Ty < ' _ > ) -> ControlFlow < Self :: BreakTy > {
475
481
match t. kind ( ) {
476
482
ty:: Dynamic ( preds, RegionKind :: ReStatic ) => {
477
483
if let Some ( def_id) = preds. principal_def_id ( ) {
478
- self . 0 . push ( def_id) ;
484
+ self . 0 . insert ( def_id) ;
479
485
}
480
486
ControlFlow :: CONTINUE
481
487
}
@@ -485,9 +491,9 @@ impl TypeVisitor<'_> for TraitObjectVisitor {
485
491
}
486
492
487
493
/// Collect all `hir::Ty<'_>` `Span`s for trait objects with an implicit lifetime.
488
- struct HirTraitObjectVisitor ( Vec < Span > , DefId ) ;
494
+ pub ( super ) struct HirTraitObjectVisitor < ' a > ( pub ( super ) & ' a mut Vec < Span > , pub ( super ) DefId ) ;
489
495
490
- impl < ' tcx > Visitor < ' tcx > for HirTraitObjectVisitor {
496
+ impl < ' a , ' tcx > Visitor < ' tcx > for HirTraitObjectVisitor < ' a > {
491
497
type Map = ErasedMap < ' tcx > ;
492
498
493
499
fn nested_visit_map ( & mut self ) -> NestedVisitorMap < Self :: Map > {
0 commit comments