@@ -8,7 +8,7 @@ extern crate rustc_middle;
88extern crate rustc_span;
99
1010use crate :: format_cc_ident;
11- use crate :: format_type:: CcParamTy ;
11+ use crate :: format_type:: { format_param_types_for_cc , CcParamTy } ;
1212use crate :: generate_doc_comment;
1313use crate :: generate_function:: {
1414 format_variant_ctor_cc_name, generate_thunk_call, Param , ThunkSelfParameter ,
@@ -26,12 +26,17 @@ use database::{AdtCoreBindings, BindingsGenerator, TypeLocation};
2626use error_report:: { anyhow, bail, ensure} ;
2727use itertools:: Itertools ;
2828use proc_macro2:: { Ident , Literal , TokenStream } ;
29- use query_compiler:: post_analysis_typing_env;
29+ use query_compiler:: {
30+ liberate_and_deanonymize_late_bound_regions, post_analysis_typing_env, try_normalize,
31+ } ;
3032use quote:: { format_ident, quote} ;
3133use rustc_abi:: { Endian , FieldsShape , VariantIdx , Variants } ;
34+ use rustc_infer:: infer:: { RegionVariableOrigin , TyCtxtInferExt } ;
3235use rustc_middle:: mir:: interpret:: Scalar ;
3336use rustc_middle:: mir:: ConstValue ;
34- use rustc_middle:: ty:: { self , AssocKind , IntTy , Ty , TyCtxt , TyKind , TypeFlags , TypingEnv , UintTy } ;
37+ use rustc_middle:: ty:: {
38+ self , AssocKind , IntTy , Region , Ty , TyCtxt , TyKind , TypeFlags , TypingEnv , TypingMode , UintTy ,
39+ } ;
3540use rustc_span:: def_id:: { CrateNum , DefId , LOCAL_CRATE } ;
3641use rustc_span:: symbol:: sym;
3742use std:: collections:: { BTreeSet , HashMap , HashSet } ;
@@ -574,7 +579,7 @@ fn generate_index_impls<'tcx>(
574579
575580 let query_index_impls = |index_trait : DefId ,
576581 method_this_qualifier : TokenStream ,
577- to_ref : fn ( TyCtxt < ' tcx > , Ty < ' tcx > ) -> Ty < ' tcx > |
582+ to_ref : fn ( TyCtxt < ' tcx > , Region < ' tcx > , Ty < ' tcx > ) -> Ty < ' tcx > |
578583 -> IndexImpls < ' tcx > {
579584 let mut has_usize_impl = false ;
580585 let mut has_isize_impl = false ;
@@ -588,32 +593,37 @@ fn generate_index_impls<'tcx>(
588593 . expect ( "DefId for an `Index` trait impl lacked a trait header" ) ;
589594 // Index 0 of our trait ref is the self type, so index 1 is the type we're converting
590595 // into.
591- let index_element_ty =
592- middle_trait_header. trait_ref . instantiate_identity ( ) . args . type_at ( 1 ) ;
596+ let trait_args = middle_trait_header. trait_ref . instantiate_identity ( ) . args ;
597+ let index_element_ty = trait_args. type_at ( 1 ) ;
598+ if index_element_ty. flags ( ) . intersects ( has_type_or_const_vars ( ) ) {
599+ return Err ( ( anyhow ! ( "Index trait impl has uninstantiated generic parameters, which is not yet supported {index_element_ty}" ) , index_impl_id) ) ;
600+ }
593601
594602 if index_element_ty. is_usize ( ) {
595603 has_usize_impl = true ;
596604 } else if matches ! ( index_element_ty. kind( ) , TyKind :: Int ( IntTy :: Isize ) ) {
597605 has_isize_impl = true ;
598606 }
599- let index_cc_ty = db
600- . format_ty_for_cc ( index_element_ty, TypeLocation :: FnParam { is_self_param : false , elided_is_output : false } )
601- . map_err ( |e| ( e, index_impl_id) ) ?;
602607
603- let index_assoc_fn = tcx. associated_items ( index_impl_id )
608+ let index_trait_assoc_fn = tcx. associated_items ( index_trait )
604609 . in_definition_order ( )
605610 . filter ( |assoc_item| matches ! ( assoc_item. kind, AssocKind :: Fn { .. } ) )
606611 // For `Index` or `IndexMut`, we expect exactly one associated fn.
607612 . exactly_one ( )
608- . map_err ( |_| ( anyhow ! ( "{} impl expected to have a single function" , tcx. def_path_str( index_trait) ) , index_impl_id) ) ?;
609-
610- let output_unnorm = tcx. fn_sig ( index_assoc_fn. def_id )
611- // Assuming that the impl is monomorphic but we might need to provide substs here.
612- . instantiate_identity ( )
613- . output ( ) ;
614- let output_ty = tcx. normalize_erasing_late_bound_regions (
615- TypingEnv :: fully_monomorphized ( ) ,
616- output_unnorm) ;
613+ . map_err ( |_| ( anyhow ! ( "{} impl expected to have a single function" , tcx. def_path_str( index_trait) ) , index_trait) ) ?;
614+
615+ let unnorm_fn_sig =
616+ liberate_and_deanonymize_late_bound_regions (
617+ tcx,
618+ tcx. fn_sig ( index_trait_assoc_fn. def_id ) . instantiate ( tcx, trait_args) ,
619+ index_trait_assoc_fn. def_id ) ;
620+ println ! ( "unnorm_fn_sig: {:?}" , unnorm_fn_sig) ;
621+ let fn_sig = try_normalize ( tcx,
622+ ty:: PseudoCanonicalInput {
623+ typing_env : TypingEnv :: fully_monomorphized ( ) ,
624+ value : unnorm_fn_sig,
625+ } ) . expect ( "Please file a bug at crubit.rs-bug. We failed to normalize the function signature of an `Index` impl." ) ;
626+ let output_ty = fn_sig. output ( ) ;
617627
618628 // Index::Output isn't the real return type of our index method. We need to wrap it in a
619629 // reference before formatting, so that Output types like `str` are formatted correctly as
@@ -644,16 +654,13 @@ fn generate_index_impls<'tcx>(
644654 let cc_thunk_decls = cc_thunk_decls. into_tokens ( & mut prereqs) ;
645655 let doc_comment = generate_doc_comment ( db, index_impl_id) ;
646656
647- let self_by_ref = to_ref ( tcx, core. self_ty ) ;
648- let self_cpp_ty = db
649- . format_ty_for_cc (
650- self_by_ref,
651- TypeLocation :: FnParam { is_self_param : true , elided_is_output : true } ,
652- )
653- . expect (
654- "ADT's self type should be C++-convertible after generate_adt_core succeeds" ,
655- ) ;
656- let self_cpp_ty = self_cpp_ty. into_tokens ( & mut prereqs) ;
657+ let infcx = tcx. infer_ctxt ( ) . build ( TypingMode :: non_body_analysis ( ) ) ;
658+ let lifetime = infcx. next_region_var ( RegionVariableOrigin :: Autoref ( tcx. def_span ( index_impl_id) ) ) ;
659+
660+ let self_by_ref = to_ref ( tcx, lifetime, core. self_ty ) ;
661+ // We know index has two params, and we use that assumption below to construct our
662+ // &[Param] slice with direct indexing.
663+ let params = format_param_types_for_cc ( db, & fn_sig, /*has_self_param=*/ true ) . map_err ( |e| ( e, index_impl_id) ) ?;
657664 let impl_body = generate_thunk_call (
658665 db,
659666 index_impl_id,
@@ -666,22 +673,16 @@ fn generate_index_impls<'tcx>(
666673 ) ,
667674 & [ Param {
668675 cc_name : format_ident ! ( "self" ) ,
669- cpp_type : CcParamTy {
670- snippet : CcSnippet :: new ( self_cpp_ty) ,
671- is_lifetime_bound : false ,
672- } ,
673- ty : self_by_ref,
676+ cpp_type : params[ 0 ] . clone ( ) ,
677+ ty : fn_sig. inputs ( ) [ 0 ] ,
674678 } , Param {
675679 cc_name : format_ident ! ( "index" ) ,
676- cpp_type : CcParamTy {
677- snippet : index_cc_ty. clone ( ) ,
678- is_lifetime_bound : false ,
679- } ,
680- ty : index_element_ty,
680+ cpp_type : params[ 1 ] . clone ( ) ,
681+ ty : fn_sig. inputs ( ) [ 1 ] ,
681682 } ] ,
682683 ) . map_err ( |e| ( e, index_impl_id) ) ?;
683684
684- let index_cc_ty = index_cc_ty . into_tokens ( & mut prereqs) ;
685+ let index_cc_ty = params [ 1 ] . snippet . clone ( ) . into_tokens ( & mut prereqs) ;
685686 let impl_body_tokens = impl_body. into_tokens ( & mut prereqs) ;
686687 prereqs. move_defs_to_fwd_decls ( ) ;
687688
@@ -716,12 +717,12 @@ fn generate_index_impls<'tcx>(
716717 let index_impls: IndexImpls < ' tcx > = query_index_impls (
717718 tcx. lang_items ( ) . index_trait ( ) . expect ( "Could not find Index trait" ) ,
718719 quote ! { const & } ,
719- |tcx , ty| Ty :: new_imm_ref ( tcx , tcx . lifetimes . re_static , ty ) ,
720+ Ty :: new_imm_ref,
720721 ) ;
721722 let index_mut_impls: IndexImpls < ' tcx > = query_index_impls (
722723 tcx. lang_items ( ) . index_mut_trait ( ) . expect ( "Could not find IndexMut trait" ) ,
723724 quote ! { & } ,
724- |tcx , ty| Ty :: new_mut_ref ( tcx , tcx . lifetimes . re_static , ty ) ,
725+ Ty :: new_mut_ref,
725726 ) ;
726727
727728 index_impls. into_iter ( db) . chain ( index_mut_impls. into_iter ( db) ) . collect ( )
0 commit comments