|  | 
| 1 | 1 | use std::assert_matches::assert_matches; | 
| 2 | 2 | 
 | 
| 3 |  | -use hir::{HirId, Node}; | 
|  | 3 | +use hir::Node; | 
| 4 | 4 | use rustc_data_structures::fx::FxIndexSet; | 
| 5 | 5 | use rustc_hir as hir; | 
| 6 | 6 | use rustc_hir::def::DefKind; | 
| 7 | 7 | use rustc_hir::def_id::{DefId, LocalDefId}; | 
| 8 |  | -use rustc_hir::intravisit::{self, Visitor}; | 
| 9 |  | -use rustc_middle::ty::{self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, Upcast}; | 
|  | 8 | +use rustc_middle::ty::{ | 
|  | 9 | +    self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast, | 
|  | 10 | +}; | 
| 10 | 11 | use rustc_middle::{bug, span_bug}; | 
| 11 | 12 | use rustc_span::symbol::Ident; | 
| 12 | 13 | use rustc_span::{DUMMY_SP, Span}; | 
| @@ -305,7 +306,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen | 
| 305 | 306 |     } | 
| 306 | 307 | 
 | 
| 307 | 308 |     if tcx.features().generic_const_exprs() { | 
| 308 |  | -        predicates.extend(const_evaluatable_predicates_of(tcx, def_id)); | 
|  | 309 | +        predicates.extend(const_evaluatable_predicates_of(tcx, def_id, &predicates)); | 
| 309 | 310 |     } | 
| 310 | 311 | 
 | 
| 311 | 312 |     let mut predicates: Vec<_> = predicates.into_iter().collect(); | 
| @@ -369,61 +370,81 @@ fn compute_bidirectional_outlives_predicates<'tcx>( | 
| 369 | 370 |     } | 
| 370 | 371 | } | 
| 371 | 372 | 
 | 
| 372 |  | -fn const_evaluatable_predicates_of( | 
| 373 |  | -    tcx: TyCtxt<'_>, | 
|  | 373 | +#[instrument(level = "debug", skip(tcx, predicates), ret)] | 
|  | 374 | +fn const_evaluatable_predicates_of<'tcx>( | 
|  | 375 | +    tcx: TyCtxt<'tcx>, | 
| 374 | 376 |     def_id: LocalDefId, | 
| 375 |  | -) -> FxIndexSet<(ty::Clause<'_>, Span)> { | 
|  | 377 | +    predicates: &FxIndexSet<(ty::Clause<'tcx>, Span)>, | 
|  | 378 | +) -> FxIndexSet<(ty::Clause<'tcx>, Span)> { | 
| 376 | 379 |     struct ConstCollector<'tcx> { | 
| 377 | 380 |         tcx: TyCtxt<'tcx>, | 
| 378 | 381 |         preds: FxIndexSet<(ty::Clause<'tcx>, Span)>, | 
| 379 | 382 |     } | 
| 380 | 383 | 
 | 
| 381 |  | -    impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> { | 
| 382 |  | -        fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { | 
| 383 |  | -            let ct = ty::Const::from_anon_const(self.tcx, c.def_id); | 
| 384 |  | -            if let ty::ConstKind::Unevaluated(_) = ct.kind() { | 
| 385 |  | -                let span = self.tcx.def_span(c.def_id); | 
| 386 |  | -                self.preds.insert((ty::ClauseKind::ConstEvaluatable(ct).upcast(self.tcx), span)); | 
| 387 |  | -            } | 
| 388 |  | -        } | 
|  | 384 | +    fn is_const_param_default(tcx: TyCtxt<'_>, def: LocalDefId) -> bool { | 
|  | 385 | +        let hir_id = tcx.local_def_id_to_hir_id(def); | 
|  | 386 | +        let (_, parent_node) = tcx | 
|  | 387 | +            .hir() | 
|  | 388 | +            .parent_iter(hir_id) | 
|  | 389 | +            .skip_while(|(_, n)| matches!(n, Node::ConstArg(..))) | 
|  | 390 | +            .next() | 
|  | 391 | +            .unwrap(); | 
|  | 392 | +        debug!(?parent_node); | 
|  | 393 | +        matches!( | 
|  | 394 | +            parent_node, | 
|  | 395 | +            Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { .. }, .. }) | 
|  | 396 | +        ) | 
|  | 397 | +    } | 
| 389 | 398 | 
 | 
| 390 |  | -        fn visit_const_param_default(&mut self, _param: HirId, _ct: &'tcx hir::ConstArg<'tcx>) { | 
| 391 |  | -            // Do not look into const param defaults, | 
| 392 |  | -            // these get checked when they are actually instantiated. | 
| 393 |  | -            // | 
| 394 |  | -            // We do not want the following to error: | 
| 395 |  | -            // | 
| 396 |  | -            //     struct Foo<const N: usize, const M: usize = { N + 1 }>; | 
| 397 |  | -            //     struct Bar<const N: usize>(Foo<N, 3>); | 
|  | 399 | +    impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstCollector<'tcx> { | 
|  | 400 | +        fn visit_const(&mut self, c: ty::Const<'tcx>) { | 
|  | 401 | +            if let ty::ConstKind::Unevaluated(uv) = c.kind() { | 
|  | 402 | +                if is_const_param_default(self.tcx, uv.def.expect_local()) { | 
|  | 403 | +                    // Do not look into const param defaults, | 
|  | 404 | +                    // these get checked when they are actually instantiated. | 
|  | 405 | +                    // | 
|  | 406 | +                    // We do not want the following to error: | 
|  | 407 | +                    // | 
|  | 408 | +                    //     struct Foo<const N: usize, const M: usize = { N + 1 }>; | 
|  | 409 | +                    //     struct Bar<const N: usize>(Foo<N, 3>); | 
|  | 410 | +                    return; | 
|  | 411 | +                } | 
|  | 412 | + | 
|  | 413 | +                let span = self.tcx.def_span(uv.def); | 
|  | 414 | +                self.preds.insert((ty::ClauseKind::ConstEvaluatable(c).upcast(self.tcx), span)); | 
|  | 415 | +            } | 
| 398 | 416 |         } | 
| 399 | 417 |     } | 
| 400 | 418 | 
 | 
| 401 | 419 |     let hir_id = tcx.local_def_id_to_hir_id(def_id); | 
| 402 | 420 |     let node = tcx.hir_node(hir_id); | 
| 403 | 421 | 
 | 
| 404 | 422 |     let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() }; | 
|  | 423 | + | 
|  | 424 | +    for (clause, _sp) in predicates { | 
|  | 425 | +        clause.visit_with(&mut collector); | 
|  | 426 | +    } | 
|  | 427 | + | 
| 405 | 428 |     if let hir::Node::Item(item) = node | 
| 406 |  | -        && let hir::ItemKind::Impl(impl_) = item.kind | 
|  | 429 | +        && let hir::ItemKind::Impl(_) = item.kind | 
| 407 | 430 |     { | 
| 408 |  | -        if let Some(of_trait) = &impl_.of_trait { | 
| 409 |  | -            debug!("const_evaluatable_predicates_of({:?}): visit impl trait_ref", def_id); | 
| 410 |  | -            collector.visit_trait_ref(of_trait); | 
|  | 431 | +        if let Some(of_trait) = tcx.impl_trait_ref(def_id) { | 
|  | 432 | +            debug!("visit impl trait_ref"); | 
|  | 433 | +            of_trait.instantiate_identity().visit_with(&mut collector); | 
| 411 | 434 |         } | 
| 412 | 435 | 
 | 
| 413 |  | -        debug!("const_evaluatable_predicates_of({:?}): visit_self_ty", def_id); | 
| 414 |  | -        collector.visit_ty(impl_.self_ty); | 
| 415 |  | -    } | 
| 416 |  | - | 
| 417 |  | -    if let Some(generics) = node.generics() { | 
| 418 |  | -        debug!("const_evaluatable_predicates_of({:?}): visit_generics", def_id); | 
| 419 |  | -        collector.visit_generics(generics); | 
|  | 436 | +        debug!("visit self_ty"); | 
|  | 437 | +        let self_ty = tcx.type_of(def_id); | 
|  | 438 | +        self_ty.instantiate_identity().visit_with(&mut collector); | 
| 420 | 439 |     } | 
| 421 | 440 | 
 | 
| 422 |  | -    if let Some(fn_sig) = tcx.hir().fn_sig_by_hir_id(hir_id) { | 
| 423 |  | -        debug!("const_evaluatable_predicates_of({:?}): visit_fn_decl", def_id); | 
| 424 |  | -        collector.visit_fn_decl(fn_sig.decl); | 
|  | 441 | +    if let Some(_) = tcx.hir().fn_sig_by_hir_id(hir_id) { | 
|  | 442 | +        debug!("visit fn sig"); | 
|  | 443 | +        let fn_sig = tcx.fn_sig(def_id); | 
|  | 444 | +        let fn_sig = fn_sig.instantiate_identity(); | 
|  | 445 | +        debug!(?fn_sig); | 
|  | 446 | +        fn_sig.visit_with(&mut collector); | 
| 425 | 447 |     } | 
| 426 |  | -    debug!("const_evaluatable_predicates_of({:?}) = {:?}", def_id, collector.preds); | 
| 427 | 448 | 
 | 
| 428 | 449 |     collector.preds | 
| 429 | 450 | } | 
|  | 
0 commit comments